diff --git a/.changeset/README.md b/.changeset/README.md new file mode 100644 index 00000000..6de90c17 --- /dev/null +++ b/.changeset/README.md @@ -0,0 +1,24 @@ +# Changesets + +This directory is used by [@changesets/cli](https://github.com/changesets/changesets) to manage versioning and changelog entries for confluence.js. + +## Workflow + +1. **Make changes** — implement your feature or fix +2. **Add a changeset** — `pnpm changeset` (interactive prompt) +3. **Commit** — include the new `.md` file in your commit +4. **Release** — maintainers run `pnpm changeset:version` to bump versions, then publish + +## Changeset types + +| Type | When | +|------|------| +| `major` | Breaking changes | +| `minor` | Additive changes (new endpoints, new exports) | +| `patch` | Bug fixes, internal improvements, declaration fixes | + +## Rules + +- Every PR that affects public API **must** include a changeset +- PRs that only affect tests, docs, or CI may omit a changeset +- Breaking changes require a `major` changeset with migration guidance diff --git a/.changeset/config.json b/.changeset/config.json new file mode 100644 index 00000000..8e6693cd --- /dev/null +++ b/.changeset/config.json @@ -0,0 +1,11 @@ +{ + "$schema": "https://unpkg.com/@changesets/config/schema.json", + "changelog": "@changesets/cli/changelog", + "commit": false, + "fixed": [], + "linked": [], + "access": "public", + "baseBranch": "master", + "updateInternalDependencies": "patch", + "ignore": [] +} diff --git a/.changeset/tall-cameras-shake.md b/.changeset/tall-cameras-shake.md new file mode 100644 index 00000000..d22d71f6 --- /dev/null +++ b/.changeset/tall-cameras-shake.md @@ -0,0 +1,119 @@ +--- +'confluence.js': major +--- + +**confluence.js 3.0 — both Confluence Cloud APIs from one package.** + +The library now covers Cloud REST **v2** (30 namespaces, 218 methods) alongside +**v1** (28 namespaces, 130 methods). Both are first-class: Atlassian has not +deprecated v1, and the two cover different ground. One `host` and one client +serve both — the API path belongs to the request, not to your config. + +Runtime dependencies are down to `zod` alone. axios, form-data, oauth and +atlassian-jwt are gone with the old transport, which is now the built-in `fetch`. +Every response is validated against a Zod 4 schema, so API drift raises a +`SchemaMismatchError` instead of surfacing as `undefined` later on. + +```ts +import { createV2Client } from 'confluence.js'; + +const confluence = createV2Client({ + host: 'https://your-domain.atlassian.net', + auth: { type: 'basic', email, apiToken }, +}); + +await confluence.page.getPages({ spaceId: ['123'] }); +``` + +Or import just what you call — the package is ESM-only and tree-shakable, with +entry points at `confluence.js/v1`, `confluence.js/v2` and `confluence.js/core`. + +**OAuth 2.0 (3LO)** is a first-class strategy. Hand over your app credentials and +a refresh token, and the client refreshes before expiry, retries once on a `401`, +resolves the cloud id, and routes through the Atlassian gateway — where 3LO tokens +are actually accepted: + +```ts +const confluence = createV2Client({ + auth: { + type: 'oauth2', + clientId, + clientSecret, + refreshToken, + onTokenRefresh: ({ refreshToken }) => tokenStore.save(refreshToken), + }, +}); +``` + +The flow itself is covered too, so no separate OAuth library is needed: +`generateAuthorizationUrl`, `parseCallbackUrl`, `exchangeAuthorizationCode`, +`refreshOAuth2Token` and `getAccessibleResources`. + +Both version factories accept an existing client, so v1 and v2 can share one +OAuth token — building one each would make the first refresh invalidate the +other's rotating refresh token: + +```ts +const client = createClient({ auth: { type: 'oauth2', … } }); + +const v1 = createV1Client(client); +const v2 = createV2Client(client); +``` + +**Node and the browser, from one build.** There is no separate web build: the code +branches on what the runtime supports rather than on which runtime it is. It loads +from a dependency-resolving CDN as published, and a self-contained `dist/browser.js` +with zod inlined covers plain file hosts and ` +``` + +Attachments accept the same values everywhere — a `File`, `Blob`, `Uint8Array`, +string, stream, and still Node's `Buffer` and `Readable`, which are a `Uint8Array` +and an `AsyncIterable` respectively. They are no longer *named* in `AttachmentContent`, +so the shipped declarations compile in a project without `@types/node`. Where a +browser cannot send a request body as a stream, the stream is read into a `Blob` +rather than failing. See the [browser guide](https://mrrefactoring.github.io/confluence.js/guide/browser). + +**Every failure has a type.** Non-2xx responses throw an `ApiError` subclass — +`AuthError`, `ForbiddenError`, `NotFoundError`, `RateLimitError` (with +`retryAfterMs` parsed from `Retry-After`), `ServerError`. Transport faults throw +`NetworkError` instead of leaking a raw `fetch` `TypeError`, and OAuth failures +throw `OAuthError`. A 2xx whose body does not match the schema throws +`SchemaMismatchError`, carrying the raw `body` and, when the shape drifted, the +underlying `ZodError` on `cause`. Each ships an `isXxx` predicate that checks a branded marker +rather than the prototype chain, so narrowing survives two copies of the package +in one `node_modules`: + +```ts +import { isNotFoundError, isRateLimitError } from 'confluence.js'; + +if (isNotFoundError(error)) return null; +if (isRateLimitError(error)) await sleep(error.retryAfterMs ?? 60_000); +``` + +### Breaking changes + +- `new ConfluenceClient({…})` → `createV1Client({…})` / `createV2Client({…})` +- `authentication: { basic: {…} }` → `auth: { type: 'basic', … }`; `oauth2` → `auth: { type: 'oauth2', … }` +- JWT (Atlassian Connect) authentication is not supported — Connect apps should stay on `confluence.js@2` +- Callbacks, `middlewares`, `apiPrefix` and `baseRequestConfig` are removed +- `noCheckAtlassianToken` is removed with nothing to replace it: v1 enforces XSRF + on every write, so every v1 write now sends `X-Atlassian-Token: no-check` itself +- `BaseClient` and the per-namespace classes are gone, as are deep imports like `confluence.js/api/content` +- Errors are `ApiError` and its subclasses (`status`, `statusText`, `body`) rather + than `AxiosError`; transport faults are `NetworkError`, OAuth failures are `OAuthError` +- `AttachmentContent` no longer names `Buffer` or `Readable`. Both still work — the + type describes them structurally — but a declaration that required `@types/node` + broke every browser consumer +- `createMultipartRequestBody` returns a `Promise`: collecting a stream for a runtime + that cannot send one is asynchronous +- The v1 surface follows Atlassian's current spec, which has dropped 37 operations + (`getContent`, `createContent`, `getSpace`, …) since 2.x shipped — each is mapped + to its v2 equivalent in the migration guide + +See [MIGRATION.md](https://github.com/MrRefactoring/confluence.js/blob/master/MIGRATION.md); +a codemod handles the mechanical parts. diff --git a/.github/workflows/changeset-check.yml b/.github/workflows/changeset-check.yml new file mode 100644 index 00000000..1fadd0d1 --- /dev/null +++ b/.github/workflows/changeset-check.yml @@ -0,0 +1,65 @@ +name: 📦 Changeset Check + +on: + pull_request: + branches: + - master + - develop + +jobs: + changeset-check: + name: 📦 Changeset Required + runs-on: ubuntu-latest + permissions: + contents: read + steps: + - name: 🔄 Checkout sources + uses: actions/checkout@v7 + with: + fetch-depth: 0 + + - name: ⚙️ Use Node.js 22.x + uses: actions/setup-node@v7 + with: + node-version: 22.x + + - name: 📦 Install pnpm + uses: pnpm/action-setup@v6 + + - name: 📌 Install dependencies + run: pnpm install --frozen-lockfile + + - name: 📦 Check for changeset + run: | + # Get list of changed files in this PR vs base branch + CHANGED=$(git diff --name-only origin/${{ github.base_ref }}...HEAD) + echo "Changed files:" + echo "$CHANGED" + + # Check if any package source files changed + SRC_CHANGED=$(echo "$CHANGED" | grep -E '^packages/[^/]+/src/' || true) + + if [ -z "$SRC_CHANGED" ]; then + echo "✅ No package source files changed — changeset not required" + exit 0 + fi + + echo "Source files changed:" + echo "$SRC_CHANGED" + + # Check if any .md changeset files exist (excluding README.md) + CHANGESETS=$(ls .changeset/*.md 2>/dev/null | grep -v README.md || true) + + if [ -z "$CHANGESETS" ]; then + echo "" + echo "❌ Package source files changed but no changeset found." + echo "" + echo " Run: pnpm changeset" + echo " This creates a changeset file describing the impact of your changes." + echo " See .changeset/README.md for guidance." + echo "" + exit 1 + fi + + echo "✅ Changeset found:" + echo "$CHANGESETS" diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index e4e77615..ea221280 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -3,114 +3,89 @@ name: 🛠️ CI on: push: branches: - - '**' # Runs on all branch pushes + - '**' tags-ignore: - - '**' # Ignore all tag pushes + - '**' repository_dispatch: types: [ pr-approved ] -env: - PNPM_VERSION: '10' +concurrency: + group: ci-${{ github.ref }} + cancel-in-progress: true jobs: build: - name: 🏗️ Build + name: 🏗️ Build & lint runs-on: ubuntu-latest strategy: matrix: - node-version: [20.x, 22.x] + node-version: [22.x, 24.x] steps: - name: 🔄 Checkout sources - uses: actions/checkout@v4 + uses: actions/checkout@v7 - name: ⚙️ Use Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v4 + uses: actions/setup-node@v7 with: node-version: ${{ matrix.node-version }} - name: 📦 Install pnpm - uses: pnpm/action-setup@v4 - with: - version: ${{ env.PNPM_VERSION }} - - name: 📌 Installing dependencies + uses: pnpm/action-setup@v6 + - name: 📌 Install dependencies run: pnpm install --frozen-lockfile - - name: 🛠️ Building sources + - name: 🛠️ Build run: pnpm run build - - lint: - name: 🔍 Lint Code - needs: build - runs-on: ubuntu-latest - strategy: - matrix: - node-version: [20.x, 22.x] - steps: - - name: 🔄 Checkout sources - uses: actions/checkout@v4 - - name: ⚙️ Use Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v4 - with: - node-version: ${{ matrix.node-version }} - - name: 📦 Install pnpm - uses: pnpm/action-setup@v4 - with: - version: ${{ env.PNPM_VERSION }} - - name: 📌 Installing dependencies - run: pnpm install --frozen-lockfile - - name: ✨ Linting + - name: 🔍 Lint run: pnpm run lint - env: - CI: true + - name: 🧾 Typecheck (sources and tests) + run: pnpm run typecheck - test_unit: - name: 🧪 Unit Tests + test: + name: 🧪 Unit tests needs: build runs-on: ubuntu-latest strategy: matrix: - node-version: [20.x, 22.x] + node-version: [22.x, 24.x] steps: - name: 🔄 Checkout sources - uses: actions/checkout@v4 + uses: actions/checkout@v7 - name: ⚙️ Use Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v4 + uses: actions/setup-node@v7 with: node-version: ${{ matrix.node-version }} - name: 📦 Install pnpm - uses: pnpm/action-setup@v4 - with: - version: ${{ env.PNPM_VERSION }} - - name: 📌 Installing dependencies + uses: pnpm/action-setup@v6 + - name: 📌 Install dependencies run: pnpm install --frozen-lockfile - - name: 🚀 Running unit tests - run: pnpm run test:unit + - name: 🧪 Unit tests + run: pnpm run test - test_integration: - name: 🧩 Integration Tests - needs: - - lint - - test_unit + package: + name: 📦 Package checks + needs: build runs-on: ubuntu-latest - strategy: - max-parallel: 1 - matrix: - node-version: [20.x, 22.x] steps: - name: 🔄 Checkout sources - uses: actions/checkout@v4 - - name: ⚙️ Use Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v4 + uses: actions/checkout@v7 + - name: ⚙️ Use Node.js 22.x + uses: actions/setup-node@v7 with: - node-version: ${{ matrix.node-version }} + node-version: 22.x - name: 📦 Install pnpm - uses: pnpm/action-setup@v4 - with: - version: ${{ env.PNPM_VERSION }} - - name: 📌 Installing dependencies + uses: pnpm/action-setup@v6 + - name: 📌 Install dependencies run: pnpm install --frozen-lockfile - - name: 📝 Creating `.env` file - run: | - touch .env - echo HOST=${{ secrets.HOST }} >> .env - echo EMAIL=${{ secrets.EMAIL }} >> .env - echo API_TOKEN=${{ secrets.API_TOKEN }} >> .env - - name: 🚀 Running integration tests - run: pnpm run test:integration + - name: 🏗️ Build + run: pnpm run build + - name: 🔎 Are the types wrong? + run: pnpm run check:attw + - name: 🚚 Consumer smoke tests + run: pnpm run check:consumers + # Static: nothing Node-only is named in the runtime or in the declarations. + - name: 🌐 Browser-safe build + run: pnpm run check:browser + # Live: the built package actually loads and works in a browser. Kept in + # this job so the browser download only happens once per run. + - name: 🎭 Install Chromium + run: pnpm exec playwright install --with-deps chromium + - name: 🌍 Browser smoke tests + run: pnpm run check:browser:e2e diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml new file mode 100644 index 00000000..2aea7922 --- /dev/null +++ b/.github/workflows/docs.yml @@ -0,0 +1,62 @@ +name: Docs + +on: + push: + branches: [master] + paths: + - 'docs/**' + - 'src/**' + - 'scripts/prepare-api-docs.ts' + - 'typedoc.json' + - 'package.json' + - 'pnpm-lock.yaml' + - '.github/workflows/docs.yml' + workflow_dispatch: + +permissions: + contents: read + pages: write + id-token: write + +concurrency: + group: pages + cancel-in-progress: false + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v7 + + - uses: pnpm/action-setup@v6 + + - uses: actions/setup-node@v7 + with: + node-version: 22 + cache: pnpm + + - name: Install dependencies + run: pnpm install --frozen-lockfile + + # Builds the API reference from src, then the site around it. Dead links are + # not ignored, so a broken cross-reference fails here rather than shipping. + - name: Build docs + run: pnpm run docs:build + env: + NODE_OPTIONS: --max-old-space-size=8192 + + - uses: actions/configure-pages@v6 + + - uses: actions/upload-pages-artifact@v5 + with: + path: docs/.vitepress/dist + + deploy: + needs: build + runs-on: ubuntu-latest + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + steps: + - id: deployment + uses: actions/deploy-pages@v5 diff --git a/.github/workflows/live-tests.yaml b/.github/workflows/live-tests.yaml new file mode 100644 index 00000000..b23cb19b --- /dev/null +++ b/.github/workflows/live-tests.yaml @@ -0,0 +1,57 @@ +name: 🧩 Live tests + +# The live suites create and delete real content on one shared Confluence Cloud +# site, so they cannot run on every push: parallel branches would fight over the +# same tenant, and every WIP commit would pay for a full serial run. +# +# They run where the answer matters — on pull requests, nightly against spec +# drift, and on demand. +on: + pull_request: + branches: [master, develop] + schedule: + # 03:00 UTC — catches Atlassian changing a response shape under us. + - cron: '0 3 * * *' + workflow_dispatch: + inputs: + version: + description: Which suite to run + type: choice + default: both + options: [both, v1, v2] + +# One run at a time, repo-wide: every run shares the same tenant. +concurrency: + group: live-tests + cancel-in-progress: false + +jobs: + live: + name: 🧩 ${{ github.event.inputs.version || 'both' }} + runs-on: ubuntu-latest + steps: + - name: 🔄 Checkout sources + uses: actions/checkout@v7 + # A single Node version: these tests exercise Atlassian's responses, not + # the runtime. A matrix here would only double the load on the tenant. + - name: ⚙️ Use Node.js 22.x + uses: actions/setup-node@v7 + with: + node-version: 22.x + - name: 📦 Install pnpm + uses: pnpm/action-setup@v6 + - name: 📌 Install dependencies + run: pnpm install --frozen-lockfile + - name: 📝 Creating `.env` file + run: | + touch .env + echo HOST=${{ secrets.HOST }} >> .env + echo EMAIL=${{ secrets.EMAIL }} >> .env + echo API_TOKEN=${{ secrets.API_TOKEN }} >> .env + - name: 🚀 Run live suite + run: | + case "${{ github.event.inputs.version || 'both' }}" in + v1) pnpm run test:live:v1 ;; + v2) pnpm run test:live:v2 ;; + *) pnpm run test:live ;; + esac diff --git a/.github/workflows/publish-dev.yml b/.github/workflows/publish-dev.yml index fb3dce89..9127105f 100644 --- a/.github/workflows/publish-dev.yml +++ b/.github/workflows/publish-dev.yml @@ -4,11 +4,11 @@ on: workflow_dispatch env: - NODE_VERSION: '20.x' - PNPM_VERSION: '10' + NODE_VERSION: '22.x' permissions: contents: read + id-token: write jobs: build-and-publish: @@ -16,18 +16,16 @@ jobs: steps: - name: 🔄 Checkout code - uses: actions/checkout@v4 + uses: actions/checkout@v7 - name: ⚙️ Setup Node.js ${{ env.NODE_VERSION }} - uses: actions/setup-node@v4 + uses: actions/setup-node@v7 with: node-version: ${{ env.NODE_VERSION }} registry-url: https://registry.npmjs.org/ - name: 📦 Install pnpm - uses: pnpm/action-setup@v4 - with: - version: ${{ env.PNPM_VERSION }} + uses: pnpm/action-setup@v6 - name: 📌 Install dependencies run: pnpm install --frozen-lockfile @@ -35,20 +33,16 @@ jobs: - name: 🛠️ Run build run: pnpm run build - - name: 🔖 Update package version - id: update-version - run: | - CURRENT_VERSION=$(node -p "require('./package.json').version") - TIMESTAMP=$(date -u +"%Y%m%d%H%M%S") - NEW_VERSION="${CURRENT_VERSION}-dev${TIMESTAMP}" - pnpm version --no-git-tag-version $NEW_VERSION - echo "New version: $NEW_VERSION" - echo "NEW_VERSION=$NEW_VERSION" >> $GITHUB_ENV - - - name: 🔄 Update package-lock.json - run: pnpm install - - - name: 📤 Publish to NPM Dev Channel - run: pnpm publish --tag dev --no-git-checks + # Two steps, because changesets only knows the release this branch leads to: + # it moves package.json there, then dev-version.ts turns that into + # -dev., numbering from what is already on npm. + - name: 🔖 Apply pending changesets + run: pnpm changeset version + + - name: 🔖 Stamp dev version + run: pnpm run version:dev + + - name: 📤 Publish dev snapshot to NPM + run: pnpm publish --tag dev --no-git-checks --provenance env: NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml deleted file mode 100644 index 751d0158..00000000 --- a/.github/workflows/publish.yml +++ /dev/null @@ -1,153 +0,0 @@ -name: 🚀 Publish to NPM - -on: - push: - tags: - - 'v*.*.*' - -env: - NODE_VERSION: '20.x' - PNPM_VERSION: '10' - -permissions: - contents: read - -jobs: - build-and-test: - name: 🏗️ Build and Test - runs-on: ubuntu-latest - steps: - - name: 🔄 Checkout repository - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - - name: ⚙️ Setup Node.js ${{ env.NODE_VERSION }} - uses: actions/setup-node@v4 - with: - node-version: ${{ env.NODE_VERSION }} - - - name: 📦 Install pnpm - uses: pnpm/action-setup@v4 - with: - version: ${{ env.PNPM_VERSION }} - - - name: 📌 Install dependencies - run: pnpm install --frozen-lockfile - - - name: 🛠️ Run build - run: pnpm run build - - - name: 🔍 Run lint - run: pnpm run lint - env: - CI: true - - - name: 🧪 Run unit tests - run: pnpm run test:unit - - - name: 🧩 Run integration tests - run: pnpm run test:integration - env: - HOST: ${{ secrets.HOST }} - EMAIL: ${{ secrets.EMAIL }} - API_TOKEN: ${{ secrets.API_TOKEN }} - - publish-package: - name: 🚀 Publish Package - needs: build-and-test - runs-on: ubuntu-latest - permissions: - contents: write - outputs: - version: ${{ steps.version.outputs.version }} - steps: - - name: 🔄 Checkout repository - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - - name: ⚙️ Setup Node.js ${{ env.NODE_VERSION }} - uses: actions/setup-node@v4 - with: - node-version: ${{ env.NODE_VERSION }} - registry-url: 'https://registry.npmjs.org' - - - name: 📦 Install pnpm - uses: pnpm/action-setup@v4 - with: - version: ${{ env.PNPM_VERSION }} - - - name: 🔖 Get and validate version - id: version - run: | - if [[ $GITHUB_REF == refs/tags/v* ]]; then - TAG_VERSION=${GITHUB_REF#refs/tags/v} - echo "Using version from tag: $TAG_VERSION" - CURRENT_VERSION=$(node -p "require('./package.json').version") - - if [ "$TAG_VERSION" != "$CURRENT_VERSION" ]; then - echo "Updating package version to match tag..." - npm version $TAG_VERSION --no-git-tag-version - pnpm install - git config user.name "GitHub Actions" - git config user.email "actions@github.com" - git add package.json pnpm-lock.yaml - git commit -m "Update version to $TAG_VERSION [skip ci]" - git push - fi - else - TAG_VERSION=$(node -p "require('./package.json').version") - echo "Using version from package.json: $TAG_VERSION" - fi - - echo "version=$TAG_VERSION" >> $GITHUB_OUTPUT - echo "VERSION=$TAG_VERSION" >> $GITHUB_ENV - env: - GITHUB_TOKEN: ${{ secrets.PAT }} - - - name: 📌 Install dependencies - run: pnpm install --frozen-lockfile - - - name: 🛠️ Build package - run: pnpm run build - - - name: 📤 Publish to NPM - run: pnpm publish --no-git-checks - env: - NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} - - deploy-documentation: - name: 📚 Deploy Documentation - needs: publish-package - runs-on: ubuntu-latest - steps: - - name: 🔄 Checkout repository - uses: actions/checkout@v4 - with: - ref: master - - - name: ⚙️ Setup Node.js ${{ env.NODE_VERSION }} - uses: actions/setup-node@v4 - with: - node-version: ${{ env.NODE_VERSION }} - - - name: 📦 Install pnpm - uses: pnpm/action-setup@v4 - with: - version: ${{ env.PNPM_VERSION }} - - - name: 📌 Install dependencies - run: pnpm install --frozen-lockfile - - - name: 📝 Generate documentation - run: pnpm run doc - - - name: 🚀 Deploy to docs branch - uses: JamesIves/github-pages-deploy-action@v4 - with: - branch: docs - folder: docs - clean: true - token: '${{ secrets.PAT }}' - commit-message: "docs: Update documentation for v${{ needs.publish-package.outputs.version }} [skip ci]" diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 00000000..ad82fa4d --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,65 @@ +name: 🚀 Release + +on: + push: + branches: + - master + +concurrency: ${{ github.workflow }}-${{ github.ref }} + +jobs: + release: + name: 🚀 Release + runs-on: ubuntu-latest + permissions: + contents: write # create git tags, push version commits + pull-requests: write # create "Version Packages" PR + id-token: write # npm provenance attestation + + steps: + - name: 🔄 Checkout sources + uses: actions/checkout@v7 + with: + fetch-depth: 0 + + - name: ⚙️ Use Node.js 22.x + uses: actions/setup-node@v7 + with: + node-version: 22.x + registry-url: https://registry.npmjs.org + + - name: 📦 Install pnpm + uses: pnpm/action-setup@v6 + + - name: 📌 Install dependencies + run: pnpm install --frozen-lockfile + + - name: 🏗️ Build + run: pnpm run build + + - name: 🧪 Unit tests + run: pnpm run test + + # What building cannot prove: that the exports map resolves and the packed + # tarball actually imports. Publishing a broken one is not undoable. + - name: 🔎 Are the types wrong? + run: pnpm run check:attw + + - name: 🚚 Consumer smoke tests + run: pnpm run check:consumers + + # Changesets action: + # - If changesets are pending → creates/updates "Version Packages" PR + # - If this IS the version commit (no pending changesets) → publishes to npm + - name: 📦 Create Release PR or Publish + id: changesets + uses: changesets/action@v1 + with: + publish: pnpm run release:publish + version: pnpm run changeset:version + title: 'chore(release): version packages' + commit: 'chore(release): version packages' + createGithubReleases: true + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} diff --git a/.gitignore b/.gitignore index 1b46ebbd..ab3cff7d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,16 @@ .idea/ node_modules/ dist/ -docs/ +coverage/ + +# The API reference (typedoc output) and the built site. The docs sources beside +# them are tracked — previously all of docs/ was ignored, which is why the site +# has no home in the repo yet. +docs/api/ +docs/ru/api/ +docs/.vitepress/dist/ +docs/.vitepress/cache/ +docs/.vitepress/.temp/ .DS_Store .env diff --git a/.husky/pre-push b/.husky/pre-push new file mode 100644 index 00000000..6f683da1 --- /dev/null +++ b/.husky/pre-push @@ -0,0 +1,4 @@ +pnpm run lint +pnpm run typecheck +pnpm run test +pnpm run build diff --git a/.npmignore b/.npmignore deleted file mode 100644 index 5bd71e82..00000000 --- a/.npmignore +++ /dev/null @@ -1,11 +0,0 @@ -.idea -.github -node_modules/ -tests/ - -.editorconfig -.eslintrc -tsconfig.lint.json -.DS_Store -.env -.env.example diff --git a/MIGRATION.md b/MIGRATION.md new file mode 100644 index 00000000..9f81edd2 --- /dev/null +++ b/MIGRATION.md @@ -0,0 +1,327 @@ +# Migrating from 2.x to 3.0 + +3.0 reworks the public surface. This page maps every break to what replaces it. + +Most of the mechanical work is automated: + +```bash +npx jscodeshift -t node_modules/confluence.js/tools/codemod/v2-to-v3.ts --parser ts --extensions ts,tsx,js,jsx src/ +``` + +The codemod rewrites the constructor, the config shape and the import paths, and +leaves a `TODO(confluence.js@3)` comment wherever a decision is yours to make. It +does not touch anything under [What has no automatic replacement](#what-has-no-automatic-replacement). + +## Contents + +- [The client](#the-client) +- [Configuration](#configuration) +- [Callbacks are gone](#callbacks-are-gone) +- [JWT authentication is gone](#jwt-authentication-is-gone) +- [What has no automatic replacement](#what-has-no-automatic-replacement) +- [The v1 surface follows Atlassian's current spec](#the-v1-surface-follows-atlassians-current-spec) +- [Imports and entry points](#imports-and-entry-points) +- [Errors](#errors) +- [Still on 2.x?](#still-on-2x) + +## The client + +`ConfluenceClient` was a class exposing the v1 API. It is now two factories, one +per API version: + +```diff +-import { ConfluenceClient } from 'confluence.js'; ++import { createV1Client } from 'confluence.js'; + +-const client = new ConfluenceClient({ +- host: 'https://your-domain.atlassian.net', +- authentication: { +- basic: { email: 'YOUR@EMAIL.ORG', apiToken: 'YOUR_API_TOKEN' }, +- }, +-}); ++const client = createV1Client({ ++ host: 'https://your-domain.atlassian.net', ++ auth: { type: 'basic', email: 'YOUR@EMAIL.ORG', apiToken: 'YOUR_API_TOKEN' }, ++}); +``` + +Namespaces and method names are unchanged, so calls carry over as they are: + +```typescript +await client.group.getGroups({ limit: 25 }); +``` + +`host` still takes the bare site URL, exactly as in 2.x. + +New in 3.0: `createV2Client` gives you the v2 API — 30 namespaces, 218 methods — +from the same package and the same host. See +[Choosing between v1 and v2](./README.md#choosing-between-v1-and-v2). + +## Configuration + +| 2.x | 3.0 | +|---|---| +| `authentication: { basic: { email, apiToken } }` | `auth: { type: 'basic', email, apiToken }` | +| `authentication: { oauth2: { accessToken } }` | `auth: { type: 'oauth2', accessToken, cloudId }` — see [below](#oauth-20) | +| `authentication: { jwt: { … } }` | *removed* — see [below](#jwt-authentication-is-gone) | +| `apiPrefix` | *removed* — the API path is part of the request now | +| `baseRequestConfig` | *removed* — it was an axios config; the transport is `fetch` | +| `middlewares: { onError, onResponse }` | *removed* — use `try`/`catch` | +| `noCheckAtlassianToken: true` | *removed* — v1 always sends it, see [below](#nocheckatlassiantoken) | +| — | `retry` — opt-in retry for transient transport failures | +| — | `getAuthOn401` — re-derive auth after a 401 | +| — | `auth: { type: 'oauth2' }` — 3LO with automatic refresh and cloud id resolution | + +### OAuth 2.0 + +2.x treated an OAuth token as an opaque bearer string against your site's host. That only ever worked by accident: 3LO tokens are rejected on `your-domain.atlassian.net` and are accepted solely through the Atlassian gateway. + +3.0 makes OAuth 2.0 a strategy of its own. Give it the credentials and it refreshes the token before expiry, retries once on a `401`, resolves the cloud id, and routes to `https://api.atlassian.com/ex/confluence/{cloudId}`: + +```ts +const confluence = createV2Client({ + auth: { + type: 'oauth2', + clientId, + clientSecret, + refreshToken, + onTokenRefresh: ({ refreshToken }) => tokenStore.save(refreshToken), + }, +}); +``` + +`host` is not passed — the gateway URL is derived. If you keep managing tokens yourself, `auth: { type: 'oauth2', accessToken, cloudId }` behaves like the 2.x setup, minus the wrong base URL. + +Persist the rotated `refreshToken` from `onTokenRefresh`: Atlassian invalidates the previous one on every refresh, and losing it costs the user another consent screen. + +The 3LO flow helpers are exported from the package root: `generateAuthorizationUrl`, `exchangeAuthorizationCode`, `refreshOAuth2Token`, `getAccessibleResources`. + +### `apiPrefix` + +In 2.x the client prepended `apiPrefix` (default `/wiki/rest/`) to every URL. In +3.0 the API path is part of each request URL, which is what lets one +client serve both versions. If you used `apiPrefix` to route through a proxy, put +the prefix in `host` instead: + +```diff +-const client = new ConfluenceClient({ host: 'https://proxy.internal', apiPrefix: '/confluence/wiki/rest/' }); ++const client = createV1Client({ host: 'https://proxy.internal/confluence' }); +``` + +### `noCheckAtlassianToken` + +v1 enforces XSRF protection on every write: without `X-Atlassian-Token: no-check` +each one answers `403 XSRF check failed`. In 2.x that was yours to opt into, and +forgetting it was the usual first 403. In 3.0 every v1 write sends the header +itself, so the option is gone with nothing to replace it: + +```diff +-const client = new ConfluenceClient({ host, authentication, noCheckAtlassianToken: true }); ++const client = createV1Client({ host, auth }); +``` + +The codemod deletes the option for you. v2 has no such requirement. + +### `middlewares` + +```diff +-const client = new ConfluenceClient({ +- host, +- authentication, +- middlewares: { +- onError: error => logger.error(error), +- onResponse: data => logger.debug(data), +- }, +-}); ++const client = createV1Client({ host, auth }); ++ ++try { ++ const data = await client.group.getGroups({}); ++ logger.debug(data); ++} catch (error) { ++ logger.error(error); ++ throw error; ++} +``` + +## Callbacks are gone + +Every method returned a promise *and* accepted a callback. 3.0 is promise-only: + +```diff +-client.group.getGroups({}, (error, data) => { +- if (error) return handle(error); +- use(data); +-}); ++try { ++ use(await client.group.getGroups({})); ++} catch (error) { ++ handle(error); ++} +``` + +## JWT authentication is gone + +2.x supported Atlassian Connect JWT via `@atlassian/atlassian-jwt`. 3.0 does not: +`auth` is `basic`, `bearer` or `oauth2` only. + +JWT is signed per request — the token depends on the request method and URL — so +it cannot be expressed as a static header, and supporting it means carrying a +crypto dependency for every user. Dropping it is what leaves `zod` as the only +runtime dependency. + +**If you build an Atlassian Connect app, stay on `confluence.js@2`.** It is not +going away, and it still gets the v1 API it always had. + +## What has no automatic replacement + +| 2.x | Why | What to do | +|---|---|---| +| `authentication.jwt` | Per-request signing, needs a crypto dependency | Stay on 2.x | +| `middlewares` | The transport no longer has an interceptor stack | `try`/`catch` around calls | +| `baseRequestConfig` | It was an axios config object | `headers` for headers; nothing else carries over | +| Callback arguments | Promise-only API | `await` | + +## The v1 surface follows Atlassian's current spec + +This is the break most likely to touch your code, and it is not one we chose. + +`confluence.js` follows Atlassian's published OpenAPI spec. +Since 2.x was released, **Atlassian removed 37 operations from the v1 spec** — +including `getContent`, `createContent` and `getSpace` — because v2 covers them. +They are gone from v1 in 3.0 for the same reason. + +Nearly all of them have a v2 equivalent: + +| 2.x — `client..` | 3.0 — `createV2Client()` | +|---|---| +| `content.getContent` | `page.getPages` / `blogPost.getBlogPosts` / `customContent.getCustomContent` | +| `content.getContentById` | `page.getPageById` / `blogPost.getBlogPostById` | +| `content.getContentByTypeForSpace`, `content.getContentForSpace` | `page.getPagesInSpace` / `blogPost.getBlogPostsInSpace` | +| `content.createContent` | `page.createPage` / `blogPost.createBlogPost` | +| `content.updateContent` | `page.updatePage` / `blogPost.updateBlogPost` | +| `content.deleteContent` | `page.deletePage` / `blogPost.deleteBlogPost` | +| `contentChildrenAndDescendants.getContentChildren`, `…ByType` | `children.getPageChildren` / `descendants.getPageDescendants` | +| `contentComments.getContentComments` | `comment.getPageFooterComments` / `comment.getPageInlineComments` | +| `contentAttachments.getAttachments` | `attachment.getPageAttachments` | +| `contentAttachments.downloadAttachment` | `attachment.getAttachmentById` then fetch `downloadLink` | +| `contentVersions.getContentVersions`, `getContentVersion` | `version.getPageVersions` / `version.getBlogPostVersions` | +| `content.getHistoryForContent` | `version.getPageVersions` | +| `contentLabels.getLabelsForContent` | `label.getPageLabels` / `label.getBlogPostLabels` | +| `contentProperties.*` | `contentProperties.getPageContentProperties` and siblings | +| `space.getSpace`, `space.getSpaces` | `space.getSpaceById` / `space.getSpaces` | +| `spaceProperties.*` | `spaceProperties.getSpaceProperties` and siblings | +| `contentBody.convertContentBody` | *no v2 equivalent* — stay on 2.x for this one | +| `inlineTasks.searchTasks`, `getTaskById`, `updateTaskById` | `task.getTasks` / `task.getTaskById` | +| `group.addUserToGroup`, `group.removeMemberFromGroup` | *no v2 equivalent* — user management moved to the [Admin API](https://developer.atlassian.com/cloud/admin/user-management/rest/) | + +One of the 37 did not move to v2 but stayed in v1 under a new name: +`contentAttachments.createAttachments` is now +`contentAttachments.createAttachment` — see [Attachment upload](#attachment-upload). + +What stayed in v1 is what v2 has no answer for: attachment upload, content +restrictions, watches, permission checks, content states, groups, relations, CQL +search, templates, themes, settings, user properties, audit records and +long-running tasks. + +This is a direction, not a one-off. `confluence.js` follows the published v1 spec +rather than freezing a private copy of the old API, and that spec keeps narrowing +as v2 grows. Expect v1 to lose more operations over time, and move each call to +v2 as soon as v2 has an equivalent. + +### Attachment upload + +Upload is v1's, and v1 keeps it — v2 reads attachments but cannot create them. +`createAttachments` is now `contentAttachments.createAttachment`, and it takes the +file content directly rather than a hand-built `FormData`: + +```diff +-await client.contentAttachments.createAttachments({ +- id: pageId, +- attachment: { file: fs.createReadStream('report.pdf') }, +-}); ++await confluence.contentAttachments.createAttachment({ ++ id: pageId, ++ attachments: { filename: 'report.pdf', content: bytes }, ++}); +``` + +`content` accepts a `string`, `Buffer`, `Blob`/`File`, a Node stream or any async +iterable of bytes, and `attachments` takes one attachment or an array of them. +`contentAttachments.downloadAttatchment` (Atlassian's spelling, kept because it is +the operation id) returns the bytes back. + +## Imports and entry points + +```diff +-import { ConfluenceClient, Config } from 'confluence.js'; +-import { Content } from 'confluence.js/api/content'; ++import { createV1Client, type ClientConfig } from 'confluence.js'; ++import { getGroups } from 'confluence.js/v1'; ++import { getPages } from 'confluence.js/v2'; ++import { createClient } from 'confluence.js/core'; +``` + +`BaseClient` and the per-namespace classes are gone. If you subclassed +`BaseClient` to assemble a narrow client, compose flat functions instead — +the result tree-shakes, which the subclass never did: + +```typescript +import { createClient } from 'confluence.js/core'; +import { getGroups } from 'confluence.js/v1'; +import { getSpaces } from 'confluence.js/v2'; + +const client = createClient({ host, auth }); + +export const custom = { + groups: () => getGroups(client, {}), + spaces: () => getSpaces(client, {}), +}; +``` + +Deep imports such as `confluence.js/api/content` no longer resolve. The entry +points are `confluence.js`, `confluence.js/v1`, `confluence.js/v2` and +`confluence.js/core`. + +## Errors + +2.x rejected with an `AxiosError`. 3.0 throws a typed error per status: + +```diff +-import type { Error as ConfluenceError } from 'confluence.js'; ++import { isNotFoundError } from 'confluence.js'; + + try { + await client.group.getGroups({}); + } catch (error) { +- if (error.response?.status === 404) { … } ++ if (isNotFoundError(error)) { … } + } +``` + +`ApiError` carries `status`, `statusText` and `body` (the parsed response body). +`AuthError` (401), `ForbiddenError` (403), `NotFoundError` (404), +`RateLimitError` (429, with `retryAfterMs`) and `ServerError` (5xx) extend it, so +catching `ApiError` still catches everything. + +Two failures that used to escape as something else now have types of their own: +a transport fault is a `NetworkError` (with `code`, `transient` and the original +error as `cause`) rather than a raw `TypeError` from `fetch`, and an OAuth 2.0 +failure is an `OAuthError` rather than a plain `Error`. + +Prefer the `isXxx` predicates over `instanceof`: they check a branded marker +instead of the prototype chain, so they still work when two copies of the package +end up installed together. + +New in 3.0: a response that does not match its schema throws a `ZodError`. That +means Atlassian's API drifted from its own spec — please +[open an issue](https://github.com/MrRefactoring/confluence.js/issues). + +## Still on 2.x? + +Staying is a legitimate choice. `confluence.js@2` keeps working and keeps its v1 +surface, including the 37 operations Atlassian has since removed from the spec. + +Stay on 2.x if you need Atlassian Connect JWT, or `convertContentBody`, or group +membership management. Otherwise 3.0 gives you v2, one runtime dependency, and +responses that are checked rather than assumed. diff --git a/README.md b/README.md index a77e639b..701d851c 100644 --- a/README.md +++ b/README.md @@ -1,248 +1,263 @@
- Confluence.js logo + Confluence.js logo NPM version NPM downloads per month build status license - JavaScript/TypeScript library for Node.js and browsers to interact with Atlassian Confluence API + Type-safe Confluence REST API client for Node.js and browsers + +

Documentation · Getting Started · API Reference · Русский

## About -Confluence.js is a powerful Node.js and browser-compatible module that provides seamless interaction with: -- [Confluence Cloud REST API](https://developer.atlassian.com/cloud/confluence/rest/) +`confluence.js` covers both Confluence Cloud REST APIs from one package: + +- **[Cloud REST API v2](https://developer.atlassian.com/cloud/confluence/rest/v2/)** — 30 namespaces, 218 methods +- **[Cloud REST API v1](https://developer.atlassian.com/cloud/confluence/rest/v1/)** — 28 namespaces, 130 methods + +Both are first-class. Atlassian has not deprecated v1, and the two cover +different ground: v1 still owns what v2 has no equivalent for, and v2 owns +everything Atlassian has moved forward. + +Every response is validated at runtime against a [Zod 4](https://zod.dev) schema +derived from Atlassian's OpenAPI spec, so API drift surfaces as a `ZodError` +rather than as `undefined` three call frames later. -Designed for developer experience and performance, it offers full API coverage and stays updated with new Confluence features. +- ESM-only, Node ≥ 22, no polyfills — the transport is the built-in `fetch` +- Tree-shakable: only the endpoints you import reach your bundle +- One runtime dependency: `zod` ## Table of Contents - [Getting Started](#getting-started) - - [Installation](#installation) - - [Quick Example](#quick-example) -- [Documentation](#documentation) -- [Usage](#usage) - - [Authentication](#authentication) - - [Basic Auth](#basic-authentication) - - [OAuth 2.0](#oauth-20) - - [JWT](#jwt) - - [First Request](#first-request) - - [API Structure](#api-structure) - - [Custom API Prefix](#custom-api-prefix) -- [Tree Shaking](#tree-shaking) +- [Authentication](#authentication) +- [Two ways to use it](#two-ways-to-use-it) +- [Choosing between v1 and v2](#choosing-between-v1-and-v2) +- [Error handling](#error-handling) +- [Retries](#retries) +- [Migrating from 2.x](#migrating-from-2x) - [Other Products](#other-products) - [License](#license) ## Getting Started -### Installation - -**Requires Node.js 20.0.0 or newer** - ```bash -# npm npm install confluence.js - -# yarn -yarn add confluence.js - -# pnpm -pnpm add confluence.js ``` -### Quick Example - -Create a Confluence space in 3 steps: - ```typescript -import { ConfluenceClient } from 'confluence.js'; +import { createV2Client } from 'confluence.js'; -const client = new ConfluenceClient({ +const confluence = createV2Client({ host: 'https://your-domain.atlassian.net', - authentication: { - basic: { - email: 'your@email.com', - apiToken: 'YOUR_API_TOKEN', // Create one: https://id.atlassian.com/manage-profile/security/api-tokens - }, + auth: { + type: 'basic', + email: 'YOUR@EMAIL.ORG', + apiToken: 'YOUR_API_TOKEN', }, }); -async function createSpace() { - const space = await client.space.createSpace({ - name: 'Project Galaxy', - key: 'GALAXY', - }); - console.log(`Space created: ${space.key}`); -} +const page = await confluence.page.createPage({ + spaceId: '123456', + title: 'Project Overview', + body: { + representation: 'storage', + value: '

Welcome to our project documentation

', + }, +}); -createSpace(); +console.log(`Page created: ${page.title}`); ``` -## Documentation - -Full API reference and guides available at: -[https://mrrefactoring.github.io/confluence.js/](https://mrrefactoring.github.io/confluence.js/) - -## Usage +`host` is your bare site URL. The API path (`/wiki/api/v2`, `/wiki/rest/api`) +belongs to the request, not to `host` — so one host serves both versions. -### Authentication +## Authentication -#### Basic Authentication +### Basic -1. Create an API token: [Atlassian Account Settings](https://id.atlassian.com/manage-profile/security/api-tokens) -2. Configure the client: +Create an API token in +[Atlassian account settings](https://id.atlassian.com/manage-profile/security/api-tokens): ```typescript -const client = new ConfluenceClient({ +const confluence = createV2Client({ host: 'https://your-domain.atlassian.net', - authentication: { - basic: { - email: 'YOUR@EMAIL.ORG', - apiToken: 'YOUR_API_TOKEN', - }, - }, + auth: { type: 'basic', email: 'YOUR@EMAIL.ORG', apiToken: 'YOUR_API_TOKEN' }, }); ``` -#### OAuth 2.0 +### OAuth 2.0 (3LO) -Implement OAuth 2.0 flow using Atlassian's [documentation](https://developer.atlassian.com/cloud/confluence/oauth-2-3lo-apps/): +Hand over your app credentials and a refresh token. The client refreshes before +expiry, retries once on a 401, and resolves the cloud id itself: ```typescript -const client = new ConfluenceClient({ - host: 'https://your-domain.atlassian.net', - authentication: { - oauth2: { - accessToken: 'YOUR_ACCESS_TOKEN', - }, +const confluence = createV2Client({ + auth: { + type: 'oauth2', + clientId: 'YOUR_CLIENT_ID', + clientSecret: 'YOUR_CLIENT_SECRET', + refreshToken: 'YOUR_REFRESH_TOKEN', + // Atlassian rotates the refresh token on every refresh — persist the new one. + onTokenRefresh: ({ refreshToken }) => tokenStore.save(refreshToken), }, }); ``` -#### JWT +No `host`: 3LO tokens only work through `api.atlassian.com`, never on your site's +own domain, so the client builds that URL from the cloud id. Pass `cloudId` or +`siteUrl` if the token can reach more than one site. + +`confluence.js` also exports the flow itself — `generateAuthorizationUrl`, +`parseCallbackUrl`, `exchangeAuthorizationCode`, `refreshOAuth2Token` and +`getAccessibleResources`. See the [OAuth 2.0 guide](https://mrrefactoring.github.io/confluence.js/guide/oauth2) +— scopes differ between v1 and v2, and refresh tokens rotate. -For server-to-server integration: +For a bearer token from somewhere other than 3LO, hand over a resolver — called +per request — and a hook to re-derive auth after a 401: ```typescript -const client = new ConfluenceClient({ +const confluence = createV2Client({ host: 'https://your-domain.atlassian.net', - authentication: { - jwt: { - issuer: 'your-client-id', - secret: 'your-secret-key', - expiryTimeSeconds: 180, - }, - }, + auth: { type: 'bearer', getToken: () => tokenStore.current() }, + getAuthOn401: async () => ({ type: 'bearer', token: await refresh() }), }); ``` -### First Request +> **JWT (Atlassian Connect) is not supported in 3.x.** See +> [MIGRATION.md](./MIGRATION.md#jwt-authentication-is-gone). + +## Two ways to use it -Create a page in an existing space: +**A client object** — the whole API behind namespaces: ```typescript -const page = await client.content.createContent({ - title: 'Project Overview', - type: 'page', - space: { key: 'GALAXY' }, - body: { - storage: { - value: '

Welcome to our project documentation

', - representation: 'storage', - }, - }, -}); +import { createV2Client } from 'confluence.js'; -console.log(`Page created: ${page.title}`); -``` +const confluence = createV2Client({ host, auth }); -### API Structure +await confluence.page.getPages({ spaceId: ['123'] }); +await confluence.space.getSpaces({ limit: 25 }); +``` -Access endpoints using `client..` pattern: +**Flat functions** — the same endpoints as standalone functions taking a client. +Nothing you do not import reaches your bundle: ```typescript -// Get space details -const space = await client.space.getSpace({ spaceKey: 'GALAXY' }); +import { createClient } from 'confluence.js/core'; +import { getPages } from 'confluence.js/v2'; + +const client = createClient({ host, auth }); -// Search content -const results = await client.search.search({ cql: 'title~"Project"' }); +await getPages(client, { spaceId: ['123'] }); ``` -
- 🔽 Available API Groups - -- [audit](https://developer.atlassian.com/cloud/confluence/rest/v1/api-group-audit/#api-group-audit) -- [analytics](https://developer.atlassian.com/cloud/confluence/rest/v1/api-group-analytics/#api-group-analytics) -- [content](https://developer.atlassian.com/cloud/confluence/rest/v1/api-group-content/#api-group-content) -- [contentAttachments](https://developer.atlassian.com/cloud/confluence/rest/v1/api-group-content---attachments/#api-group-content---attachments) -- [contentBody](https://developer.atlassian.com/cloud/confluence/rest/v1/api-group-content-body/#api-group-content-body) -- [contentChildrenAndDescendants](https://developer.atlassian.com/cloud/confluence/rest/v1/api-group-content---children-and-descendants/#api-group-content---children-and-descendants) -- contentComments - was deprecated -- [contentMacroBody](https://developer.atlassian.com/cloud/confluence/rest/v1/api-group-content---macro-body/#api-group-content---macro-body) -- [contentLabels](https://developer.atlassian.com/cloud/confluence/rest/v1/api-group-content-labels/#api-group-content-labels) -- [contentPermissions](https://developer.atlassian.com/cloud/confluence/rest/v1/api-group-content-permissions/#api-group-content-permissions) -- contentProperties - was deprecated -- [contentRestrictions](https://developer.atlassian.com/cloud/confluence/rest/v1/api-group-content-restrictions/#api-group-content-restrictions) -- [contentStates](https://developer.atlassian.com/cloud/confluence/rest/v1/api-group-content-states/#api-group-content-states) -- [contentVersions](https://developer.atlassian.com/cloud/confluence/rest/v1/api-group-content-versions/#api-group-content-versions) -- [contentWatches](https://developer.atlassian.com/cloud/confluence/rest/v1/api-group-content-watches/#api-group-content-watches) -- [dynamicModules](https://developer.atlassian.com/cloud/confluence/rest/v1/api-group-dynamic-modules/#api-group-dynamic-modules) -- [experimental](https://developer.atlassian.com/cloud/confluence/rest/v1/api-group-experimental/#api-group-experimental) -- [group](https://developer.atlassian.com/cloud/confluence/rest/v1/api-group-group/#api-group-group) -- inlineTasks - was deprecated -- [labelInfo](https://developer.atlassian.com/cloud/confluence/rest/v1/api-group-label-info/#api-group-label-info) -- [longRunningTask](https://developer.atlassian.com/cloud/confluence/rest/v1/api-group-long-running-task/#api-group-long-running-task) -- [relation](https://developer.atlassian.com/cloud/confluence/rest/v1/api-group-relation/#api-group-relation) -- [search](https://developer.atlassian.com/cloud/confluence/rest/v1/api-group-search/#api-group-search) -- [settings](https://developer.atlassian.com/cloud/confluence/rest/v1/api-group-settings/#api-group-settings) -- [space](https://developer.atlassian.com/cloud/confluence/rest/v1/api-group-space/#api-group-space) -- [spacePermissions](https://developer.atlassian.com/cloud/confluence/rest/v1/api-group-space-permissions/#api-group-space-permissions) -- spaceProperties - was deprecated -- [spaceSettings](https://developer.atlassian.com/cloud/confluence/rest/v1/api-group-space-settings/#api-group-space-settings) -- [template](https://developer.atlassian.com/cloud/confluence/rest/v1/api-group-template/#api-group-template) -- [themes](https://developer.atlassian.com/cloud/confluence/rest/v1/api-group-themes/#api-group-themes) -- [users](https://developer.atlassian.com/cloud/confluence/rest/v1/api-group-users/#api-group-users) -- [userProperties](https://developer.atlassian.com/cloud/confluence/rest/v1/api-group-user-properties/#api-group-user-properties) - -
- -### Custom API Prefix - -For custom API endpoints: +One client drives both versions: ```typescript -const client = new ConfluenceClient({ - host: 'https://custom-domain.com', - apiPrefix: '/confluence-api', // Default: '/wiki/rest/api' -}); +import { createClient } from 'confluence.js/core'; +import { getPages } from 'confluence.js/v2'; +import { getGroups } from 'confluence.js/v1'; + +const client = createClient({ host, auth }); + +await getPages(client, {}); // → /wiki/api/v2/pages +await getGroups(client, {}); // → /wiki/rest/api/group ``` -## Tree Shaking +### Entry points + +| Import | What it gives you | +|---|---| +| `confluence.js` | `createV1Client`, `createV2Client`, `ApiError`, config types | +| `confluence.js/v2` | v2 flat functions, parameter and response types | +| `confluence.js/v1` | v1 flat functions, parameter and response types | +| `confluence.js/core` | `createClient`, transport types, OAuth helpers | + +`confluence.js/v1` and `confluence.js/v2` are not re-exported from the root: the +two versions collide on a few names (`createSpace`, `getTasks`). + +## Choosing between v1 and v2 + +Reach for **v2** by default — it is where Atlassian is investing. It covers +pages, blog posts, custom content, whiteboards, databases, folders, comments, +attachments, labels, tasks, versions, spaces, space permissions and space roles. + +Reach for **v1** only for what v2 has no equivalent for: attachment *upload* (v2 +reads attachments but cannot create them), content restrictions, watches, +permission checks, content states, groups, relations, CQL search, templates, +themes, settings, user properties, audit records and long-running tasks. + +v1 is a complement to v2, not the old API kept alive. This package tracks +Atlassian's v1 spec as published, and that spec is shrinking: 37 operations that +2.x exposed — `getContent`, `createContent`, `getSpace` among them — are already +gone from it, and 33 of those have a v2 equivalent +([the map](./MIGRATION.md#the-v1-surface-follows-atlassians-current-spec)). +Expect it to narrow further, and treat a v1 call as something to move to v2 once +v2 covers it. + +## Error handling -Optimize bundle size by importing only needed modules: +Every failure is one of this package's own error types — nothing leaks from +`fetch`. Non-2xx responses throw an `ApiError` subclass carrying the status and +the parsed body; transport faults throw a `NetworkError`; the OAuth flow throws +an `OAuthError`. ```typescript -// custom-client.ts -import { BaseClient } from 'confluence.js'; -import { Content } from 'confluence.js/api/content'; -import { Space } from 'confluence.js/api/space'; - -export class CustomClient extends BaseClient { - content = new Content(this); - space = new Space(this); +import { isNotFoundError, isRateLimitError } from 'confluence.js'; + +try { + await confluence.page.getPageById({ id: 42 }); +} catch (error) { + if (isNotFoundError(error)) return null; + if (isRateLimitError(error)) await sleep(error.retryAfterMs ?? 60_000); + throw error; } +``` + +`AuthError` (401), `ForbiddenError` (403), `NotFoundError` (404), +`RateLimitError` (429) and `ServerError` (5xx) all extend `ApiError`, so +`instanceof` works — but prefer the `isXxx` predicates: they survive two copies +of the package in one `node_modules`, where `instanceof` silently returns false. + +A response that does not match its schema throws a `ZodError` instead. That +means Atlassian's API drifted from its own spec, and it is worth +[an issue](https://github.com/MrRefactoring/confluence.js/issues). + +## Retries -// Usage -const client = new CustomClient({ /* config */ }); -await client.space.getSpace({ spaceKey: 'GALAXY' }); +Off by default. When enabled, retries cover transport-layer failures only — +network errors and 502/503/504: + +```typescript +const confluence = createV2Client({ + host, + auth, + retry: { maxAttempts: 3, initialDelayMs: 500, backoffFactor: 2 }, +}); +``` + +4xx is never retried, 429 included: rate limiting is a signal to slow down, not +a transient fault to paper over. + +## Migrating from 2.x + +3.0 reworks the public surface — class clients became factories, `authentication` +became `auth`, callbacks and middlewares are gone, and the v1 surface now follows +Atlassian's current spec. See **[MIGRATION.md](./MIGRATION.md)** for the full map; +a codemod handles the mechanical parts: + +```bash +npx jscodeshift -t node_modules/confluence.js/tools/codemod/v2-to-v3.ts src/ ``` ## Other Products -Explore our other Atlassian integration libraries: -- [Jira.js](https://github.com/MrRefactoring/jira.js) - Jira API wrapper -- [Trello.js](https://github.com/MrRefactoring/trello.js) - Trello API integration +- [jira.js](https://github.com/MrRefactoring/jira.js) — Jira REST API client +- [trello.js](https://github.com/MrRefactoring/trello.js) — Trello REST API client ## License diff --git a/docs/.vitepress/config.ts b/docs/.vitepress/config.ts new file mode 100644 index 00000000..f45d86c8 --- /dev/null +++ b/docs/.vitepress/config.ts @@ -0,0 +1,205 @@ +import { defineConfig } from 'vitepress'; +import typedocSidebar from '../api/typedoc-sidebar.json' with { type: 'json' }; +import typedocSidebarRu from '../api/typedoc-sidebar.ru.json' with { type: 'json' }; + +const SITE_URL = 'https://mrrefactoring.github.io/confluence.js'; +const SITE_TITLE = 'confluence.js'; +const SITE_TAGLINE = 'Type-safe Confluence Cloud REST API client'; +const SITE_DESCRIPTION_EN = + 'Type-safe Confluence Cloud REST API client for TypeScript and JavaScript. Both API versions — v1 and v2 — from one package. ESM-only, tree-shakable, validated by Zod 4.'; +const SITE_DESCRIPTION_RU = + 'Типобезопасный клиент Confluence Cloud REST API для TypeScript и JavaScript. Обе версии API — v1 и v2 — в одном пакете. Только ESM, tree-shaking, валидация через Zod 4.'; +const OG_IMAGE = `${SITE_URL}/og-image.png`; + +const guideSidebar = (ru = false) => { + const p = ru ? '/ru' : ''; + + return [ + { + text: ru ? 'Руководство' : 'Guide', + items: [ + { text: ru ? 'Быстрый старт' : 'Getting Started', link: `${p}/guide/getting-started` }, + { text: ru ? 'Установка' : 'Installation', link: `${p}/guide/installation` }, + { text: ru ? 'Аутентификация' : 'Authentication', link: `${p}/guide/authentication` }, + { text: 'OAuth 2.0 (3LO)', link: `${p}/guide/oauth2` }, + { text: ru ? 'Выбор версии API' : 'Choosing a version', link: `${p}/guide/choosing-a-version` }, + { text: ru ? 'Обработка ошибок' : 'Error Handling', link: `${p}/guide/error-handling` }, + { text: ru ? 'Повторы запросов' : 'Retries', link: `${p}/guide/retries` }, + { text: ru ? 'Браузеры' : 'Browsers', link: `${p}/guide/browser` }, + { text: 'Tree-Shaking', link: `${p}/guide/tree-shaking` }, + { text: 'TypeScript', link: `${p}/guide/typescript` }, + ], + }, + { + text: ru ? 'Рецепты' : 'Recipes', + items: [ + { text: ru ? 'Страницы' : 'Pages', link: `${p}/recipes/pages` }, + { text: ru ? 'Пространства' : 'Spaces', link: `${p}/recipes/spaces` }, + { text: ru ? 'Вложения' : 'Attachments', link: `${p}/recipes/attachments` }, + { text: ru ? 'Поиск (CQL)' : 'Search (CQL)', link: `${p}/recipes/search` }, + { text: ru ? 'Комментарии' : 'Comments', link: `${p}/recipes/comments` }, + { text: ru ? 'Метки' : 'Labels', link: `${p}/recipes/labels` }, + { text: ru ? 'Ограничения доступа' : 'Restrictions', link: `${p}/recipes/restrictions` }, + ], + }, + { + text: ru ? 'Миграция' : 'Migration', + items: [{ text: '2.x → 3.0', link: `${p}/migration/v2-to-v3` }], + }, + ]; +}; + +const apiSidebar = [{ text: 'API Reference', items: typedocSidebar }]; +const apiSidebarRu = [{ text: 'API Reference', items: typedocSidebarRu }]; + +export default defineConfig({ + title: SITE_TITLE, + description: SITE_DESCRIPTION_EN, + base: '/confluence.js/', + cleanUrls: true, + lastUpdated: false, + + // Deliberately not ignoring anything under /api/: `docs:build` always rebuilds + // the reference first, so a dead link there is a real one worth failing on. + ignoreDeadLinks: ['localhostLinks'], + + sitemap: { hostname: `${SITE_URL}/` }, + + head: [ + // Locale auto-detection, inline so it runs before the first paint: + // - already under /ru/ → record the choice, do not redirect; + // - a Russian browser with no recorded choice → send to the RU twin of this + // exact path, preserving query and hash; + // - anything else → record 'en'. + // Once a choice is stored, this returns immediately: picking a language from + // the switcher is permanent, and a redirect must never override it. + [ + 'script', + {}, + `(function(){try{var K='confluence.js:locale',B='/confluence.js/',p=location.pathname,isRu=p.indexOf(B+'ru/')===0||p===B+'ru'||p===B+'ru/';var s=localStorage.getItem(K);if(s)return;if(isRu){localStorage.setItem(K,'ru');return;}var L=(navigator.language||'').toLowerCase();if(L.indexOf('ru')===0&&p.indexOf(B)===0){localStorage.setItem(K,'ru');location.replace(p.replace(B,B+'ru/')+location.search+location.hash);}else{localStorage.setItem(K,'en');}}catch(e){}})();`, + ], + + ['link', { rel: 'icon', href: '/confluence.js/favicon.svg', type: 'image/svg+xml' }], + ['meta', { name: 'theme-color', content: '#0052cc' }], + ['meta', { name: 'author', content: 'Vladislav Tupikin' }], + + ['meta', { property: 'og:type', content: 'website' }], + ['meta', { property: 'og:site_name', content: SITE_TITLE }], + ['meta', { property: 'og:title', content: `${SITE_TITLE} — ${SITE_TAGLINE}` }], + ['meta', { property: 'og:description', content: SITE_DESCRIPTION_EN }], + ['meta', { property: 'og:url', content: `${SITE_URL}/` }], + ['meta', { property: 'og:image', content: OG_IMAGE }], + ['meta', { property: 'og:image:width', content: '1200' }], + ['meta', { property: 'og:image:height', content: '630' }], + ['meta', { property: 'og:image:type', content: 'image/png' }], + ['meta', { property: 'og:image:alt', content: `${SITE_TITLE} — ${SITE_TAGLINE}` }], + + ['meta', { name: 'twitter:card', content: 'summary_large_image' }], + ['meta', { name: 'twitter:title', content: `${SITE_TITLE} — ${SITE_TAGLINE}` }], + ['meta', { name: 'twitter:description', content: SITE_DESCRIPTION_EN }], + ['meta', { name: 'twitter:image', content: OG_IMAGE }], + + [ + 'script', + { type: 'application/ld+json' }, + JSON.stringify({ + '@context': 'https://schema.org', + '@type': 'SoftwareSourceCode', + name: SITE_TITLE, + description: SITE_DESCRIPTION_EN, + codeRepository: 'https://github.com/MrRefactoring/confluence.js', + programmingLanguage: 'TypeScript', + runtimePlatform: 'Node.js', + license: 'https://opensource.org/licenses/MIT', + author: { '@type': 'Person', name: 'Vladislav Tupikin' }, + keywords: 'confluence, confluence-api, atlassian, typescript, esm, zod, tree-shaking, type-safe, wiki', + url: `${SITE_URL}/`, + }), + ], + ], + + transformHead: ({ pageData }) => { + const head: [string, Record][] = []; + + const relativePath = pageData.relativePath + .replace(/\.md$/, '') + .replace(/(^|\/)index$/, '$1') + .replace(/\/$/, ''); + + const isRu = relativePath === 'ru' || relativePath.startsWith('ru/'); + const enRelative = isRu ? relativePath.replace(/^ru\/?/, '') : relativePath; + const ruRelative = isRu ? relativePath : relativePath ? `ru/${relativePath}` : 'ru'; + + const url = (path: string) => `${SITE_URL}/${path ? `${path}/` : ''}`.replace(/\/+$/, '/'); + + head.push(['link', { rel: 'canonical', href: url(relativePath) }]); + head.push(['link', { rel: 'alternate', hreflang: 'en', href: url(enRelative) }]); + head.push(['link', { rel: 'alternate', hreflang: 'ru', href: url(ruRelative) }]); + head.push(['link', { rel: 'alternate', hreflang: 'x-default', href: url(enRelative) }]); + + return head; + }, + + themeConfig: { + logo: '/favicon.svg', + search: { provider: 'local' }, + socialLinks: [ + { icon: 'github', link: 'https://github.com/MrRefactoring/confluence.js' }, + { icon: 'npm', link: 'https://www.npmjs.com/package/confluence.js' }, + ], + }, + + locales: { + root: { + label: 'English', + lang: 'en-US', + description: SITE_DESCRIPTION_EN, + themeConfig: { + nav: [ + { text: 'Guide', link: '/guide/getting-started' }, + { text: 'Recipes', link: '/recipes/pages' }, + { text: 'API', link: '/api/' }, + { text: 'Migration', link: '/migration/v2-to-v3' }, + ], + sidebar: { + '/guide/': guideSidebar(), + '/recipes/': guideSidebar(), + '/migration/': guideSidebar(), + '/api/': apiSidebar, + }, + editLink: { + pattern: 'https://github.com/MrRefactoring/confluence.js/edit/master/docs/:path', + text: 'Edit this page on GitHub', + }, + outline: { label: 'On this page', level: [2, 3] }, + docFooter: { prev: 'Previous', next: 'Next' }, + }, + }, + ru: { + label: 'Русский', + lang: 'ru-RU', + link: '/ru/', + description: SITE_DESCRIPTION_RU, + themeConfig: { + nav: [ + { text: 'Руководство', link: '/ru/guide/getting-started' }, + { text: 'Рецепты', link: '/ru/recipes/pages' }, + { text: 'API', link: '/ru/api/' }, + { text: 'Миграция', link: '/ru/migration/v2-to-v3' }, + ], + sidebar: { + '/ru/guide/': guideSidebar(true), + '/ru/recipes/': guideSidebar(true), + '/ru/migration/': guideSidebar(true), + '/ru/api/': apiSidebarRu, + }, + editLink: { + pattern: 'https://github.com/MrRefactoring/confluence.js/edit/master/docs/:path', + text: 'Редактировать на GitHub', + }, + outline: { label: 'На этой странице', level: [2, 3] }, + docFooter: { prev: 'Назад', next: 'Далее' }, + }, + }, + }, +}); diff --git a/docs/guide/authentication.md b/docs/guide/authentication.md new file mode 100644 index 00000000..39f45e59 --- /dev/null +++ b/docs/guide/authentication.md @@ -0,0 +1,82 @@ +--- +title: Authentication +description: Authenticate confluence.js with an Atlassian API token or OAuth 2.0 (3LO), including automatic token refresh and cloud id resolution. +--- + +# Authentication + +Both factories take the same `auth` object, and so does `createClient` from `confluence.js/core`. + +## Basic (API token) + +The quickest way in, and the right one for scripts and back-office jobs. Create a token in [Atlassian account settings](https://id.atlassian.com/manage-profile/security/api-tokens) and pair it with the email of the same account: + +```ts +import { createV2Client } from 'confluence.js'; + +const confluence = createV2Client({ + host: 'https://your-domain.atlassian.net', + auth: { + type: 'basic', + email: process.env.CONFLUENCE_EMAIL!, + apiToken: process.env.CONFLUENCE_API_TOKEN!, + }, +}); +``` + +The client sends these as an HTTP Basic header. The token carries **your** permissions — anything it can reach, the script can reach. + +## OAuth 2.0 (3LO) + +For acting on behalf of other users. Hand over your app credentials and a refresh token, and the client refreshes before expiry, retries once on a `401`, and finds the right site: + +```ts +const confluence = createV2Client({ + auth: { + type: 'oauth2', + clientId: process.env.OAUTH_CLIENT_ID!, + clientSecret: process.env.OAUTH_CLIENT_SECRET!, + refreshToken: await tokenStore.refreshToken(), + onTokenRefresh: async ({ refreshToken, expiresAt }) => { + await tokenStore.save({ refreshToken, expiresAt }); + }, + }, +}); +``` + +There is no `host`: 3LO tokens are rejected on your site's own domain and only work through the Atlassian gateway, so the client derives that URL itself. + +3LO has enough moving parts — scope families that differ between v1 and v2, rotating refresh tokens, consent callbacks — that it gets [a guide of its own](./oauth2). Read it before wiring this up. + +## Expiring bearer tokens + +Outside 3LO — a gateway or a proxy that mints its own tokens — pass a resolver, called on **every request**: + +```ts +const confluence = createV2Client({ + host: 'https://your-domain.atlassian.net', + auth: { type: 'bearer', getToken: () => tokenStore.current() }, +}); +``` + +And when a token expires mid-flight, `getAuthOn401` re-derives auth and replays the request: + +```ts +const confluence = createV2Client({ + host: 'https://your-domain.atlassian.net', + auth: { type: 'bearer', getToken: () => tokenStore.current() }, + getAuthOn401: async () => ({ type: 'bearer', token: await refreshAccessToken() }), +}); +``` + +It fires only on a `401`, and only once per request — a second `401` is a real `ApiError`, not a retry loop. + +## JWT (Atlassian Connect) is not supported + +3.x dropped JWT. Connect apps authenticate as the *app*, with a shared secret and a signed JWT per request — a different model from the two above, and one that ties the client to the Connect lifecycle. + +If you are building a Connect app, stay on `confluence.js@2`. See [the migration guide](../migration/v2-to-v3). + +## Where the credentials go + +Your credentials reach two places and no others: the `Authorization` header of the requests you make, and — under OAuth 2.0 — Atlassian's own `auth.atlassian.com` and `api.atlassian.com` endpoints for token refresh and site lookup. There is no telemetry, no analytics and no third-party host in this package. diff --git a/docs/guide/browser.md b/docs/guide/browser.md new file mode 100644 index 00000000..1c385cd3 --- /dev/null +++ b/docs/guide/browser.md @@ -0,0 +1,88 @@ +--- +title: Browsers +description: Run confluence.js in a browser — importing from a CDN, what attachments do differently there, and why calling Confluence straight from a page is usually the wrong shape. +--- + +# Browsers + +The package runs unchanged in a browser. There is one build, not a Node build and a web build: the code branches on what the runtime can do rather than on which runtime it is. + +## Read this before you ship it + +Calling Confluence directly from a page means the browser holds a credential. + +An API token in front-end code is readable by anyone who opens devtools, and it carries the full rights of the account that issued it. An OAuth 2.0 client secret is worse, because it also lets someone mint tokens. Neither belongs in a bundle. + +Confluence Cloud also does not send CORS headers for third-party origins, so a request from your own domain is refused by the browser before it reaches Atlassian. + +That leaves two shapes that actually work: + +- **A server in front.** Your page talks to your backend, the backend holds the credential and talks to Confluence. This is the right answer for almost every product. +- **A first-party surface.** A Forge or Connect app, or an extension, where the platform supplies the origin and the credential. + +Browser support exists so those surfaces — and tooling, sandboxes, docs pages and tests — can use the same library. It is not an invitation to put a token in a web page. + +## Importing from a CDN + +Any CDN that resolves dependencies serves the package as it is published: + +```html + +``` + +jsDelivr works the same way through its `+esm` endpoint: + +```js +import { createV2Client } from 'https://cdn.jsdelivr.net/npm/confluence.js/+esm'; +``` + +The published entry imports `zod` by bare specifier, which a browser cannot resolve on its own — those CDNs rewrite it before serving. A host that returns files untouched will fail on that import. + +For those, and for a plain ` +``` + +jsDelivr делает то же через эндпоинт `+esm`: + +```js +import { createV2Client } from 'https://cdn.jsdelivr.net/npm/confluence.js/+esm'; +``` + +Опубликованная точка входа импортирует `zod` голым спецификатором, а его браузер сам разрешить не может — перечисленные CDN переписывают его перед отдачей. Хостинг, отдающий файлы как есть, на этом импорте упадёт. + +Для таких случаев и для простого ` + + + + + diff --git a/scripts/build-og-image.ts b/scripts/build-og-image.ts new file mode 100644 index 00000000..2698d940 --- /dev/null +++ b/scripts/build-og-image.ts @@ -0,0 +1,27 @@ +/** + * Rasterises `docs/public/og-image.svg` to the PNG the social meta tags point at. + * + * Crawlers do not render SVG for `og:image`, so the PNG is the artifact that + * matters and it is committed. This script only needs running when the SVG + * changes — hence it is not part of `docs:build`. + */ +import { readFileSync, writeFileSync } from 'node:fs'; +import { dirname, relative, resolve } from 'node:path'; +import { fileURLToPath } from 'node:url'; +import { Resvg } from '@resvg/resvg-js'; + +const root = resolve(dirname(fileURLToPath(import.meta.url)), '..'); +const svgPath = resolve(root, 'docs/public/og-image.svg'); +const pngPath = resolve(root, 'docs/public/og-image.png'); + +const resvg = new Resvg(readFileSync(svgPath, 'utf8'), { + fitTo: { mode: 'width', value: 1200 }, + background: 'rgba(0,0,0,0)', + font: { loadSystemFonts: true, defaultFontFamily: 'Helvetica' }, +}); + +const png = resvg.render().asPng(); + +writeFileSync(pngPath, png); + +console.log(`[build-og-image] ${relative(root, pngPath)} — ${(png.length / 1024).toFixed(1)} KB, 1200x630`); diff --git a/scripts/check-consumers.ts b/scripts/check-consumers.ts new file mode 100644 index 00000000..2ab9eaa0 --- /dev/null +++ b/scripts/check-consumers.ts @@ -0,0 +1,217 @@ +/** + * Installs the packed tarball into throwaway projects and imports it the way a + * user would. + * + * `pnpm run build` proves the sources compile; attw proves the exports map + * resolves on paper. Neither runs the published artifact. This does: it packs the + * package, installs the tarball, and drives each entry point in a real Node + * process and through a real bundler resolution. Getting `files`, `exports` or a + * dependency wrong shows up here and nowhere else. + * + * Run: pnpm run check:consumers + */ +import { execFileSync } from 'node:child_process'; +import { mkdtempSync, readdirSync, rmSync, writeFileSync, mkdirSync } from 'node:fs'; +import { tmpdir } from 'node:os'; +import { join, resolve } from 'node:path'; + +const repoRoot = resolve(import.meta.dirname, '..'); + +function run(command: string, args: string[], cwd: string): string { + return execFileSync(command, args, { cwd, encoding: 'utf8', stdio: ['ignore', 'pipe', 'pipe'] }); +} + +/** `npm pack` the repo and return the absolute path of the tarball. */ +function packTarball(into: string): string { + run('npm', ['pack', '--pack-destination', into], repoRoot); + + const tarball = readdirSync(into).find(file => file.endsWith('.tgz')); + + if (!tarball) throw new Error('npm pack produced no tarball'); + + return join(into, tarball); +} + +interface Consumer { + name: string; + /** Extra files to write into the project, keyed by relative path. */ + files: Record; + /** Argv for the command that proves the consumer works. */ + verify: (dir: string) => [string, string[]]; +} + +const CONFIG = "{ host: 'https://acme.atlassian.net', auth: { type: 'basic', email: 'a@b.co', apiToken: 'x' } }"; + +/** Runtime smoke: drives every entry point and asserts requests still carry the API path. */ +const SMOKE_JS = ` +import { createV1Client, createV2Client, ApiError } from 'confluence.js'; +import { createClient } from 'confluence.js/core'; +import { getPages } from 'confluence.js/v2'; +import { searchContentByCQL } from 'confluence.js/v1'; +import assert from 'node:assert'; + +for (const [name, value] of Object.entries({ createV1Client, createV2Client, ApiError, createClient, getPages, searchContentByCQL })) { + assert.ok(value, name + ' is missing from the published package'); +} + +const seen = []; + +globalThis.fetch = url => { + seen.push(String(url)); + + return Promise.resolve(new Response(null, { status: 204 })); +}; + +const client = createClient(${CONFIG}); + +await getPages(client, {}); +await searchContentByCQL(client, { cql: 'type=page' }); + +assert.equal(seen[0], 'https://acme.atlassian.net/wiki/api/v2/pages', 'v2 API path lost in the published build'); +assert.ok(seen[1].startsWith('https://acme.atlassian.net/wiki/rest/api/content/search'), 'v1 API path lost in the published build'); + +const v2 = createV2Client(${CONFIG}); +const v1 = createV1Client(${CONFIG}); + +assert.ok(v2.page && v2.space, 'v2 factory namespaces missing'); +assert.ok(v1.content && v1.space, 'v1 factory namespaces missing'); + +console.log(' ' + Object.keys(v2).length + ' v2 and ' + Object.keys(v1).length + ' v1 namespaces, both API paths intact'); +`; + +/** + * Type-resolution smoke. Deliberately no runtime: these consumers exist to prove + * the shipped .d.ts files resolve and infer through every subpath under strict + * settings, which is where a malformed exports map shows up. + */ +const SMOKE_TS = ` +import { createV1Client, createV2Client, ApiError } from 'confluence.js'; +import type { ClientConfig } from 'confluence.js'; +import { createClient } from 'confluence.js/core'; +import { getPages } from 'confluence.js/v2'; +import type { Page } from 'confluence.js/v2'; +import { searchContentByCQL } from 'confluence.js/v1'; + +const config: ClientConfig = ${CONFIG}; + +const client = createClient(config); +const v2 = createV2Client(config); +const v1 = createV1Client(config); + +// Inference has to survive the package boundary, not just resolve. +export async function readPage(id: string): Promise { + return v2.page.getPageById({ id: Number(id) }); +} + +export async function listPages(): Promise { + return getPages(client, {}); +} + +export async function search(cql: string): Promise { + return searchContentByCQL(client, { cql }); +} + +export async function spaces(): Promise { + return v1.space.createSpace({ key: 'X', name: 'X' }); +} + +export function isApiError(error: unknown): error is ApiError { + return error instanceof ApiError; +} +`; + +const CONSUMERS: Consumer[] = [ + { + name: 'node-esm', + files: { 'smoke.mjs': SMOKE_JS }, + verify: dir => ['node', [join(dir, 'smoke.mjs')]], + }, + { + name: 'ts-strict', + // Type resolution under the strictest settings a consumer is likely to use, + // and under node16 — the resolver that trips on a malformed exports map. + files: { + 'smoke.ts': SMOKE_TS, + 'tsconfig.json': JSON.stringify( + { + compilerOptions: { + target: 'ES2022', + module: 'node16', + moduleResolution: 'node16', + strict: true, + noEmit: true, + skipLibCheck: false, + types: ['node'], + }, + include: ['smoke.ts'], + }, + null, + 2, + ), + }, + verify: dir => [join(dir, 'node_modules/.bin/tsc'), ['-p', join(dir, 'tsconfig.json')]], + }, + { + name: 'ts-bundler', + files: { + 'smoke.ts': SMOKE_TS, + 'tsconfig.json': JSON.stringify( + { + compilerOptions: { + target: 'ES2022', + module: 'ESNext', + moduleResolution: 'bundler', + strict: true, + noEmit: true, + types: ['node'], + }, + include: ['smoke.ts'], + }, + null, + 2, + ), + }, + verify: dir => [join(dir, 'node_modules/.bin/tsc'), ['-p', join(dir, 'tsconfig.json')]], + }, +]; + +const workspace = mkdtempSync(join(tmpdir(), 'confluence-consumers-')); +let failures = 0; + +try { + console.log('packing…'); + const tarball = packTarball(workspace); + + for (const consumer of CONSUMERS) { + const dir = join(workspace, consumer.name); + + mkdirSync(dir, { recursive: true }); + writeFileSync(join(dir, 'package.json'), JSON.stringify({ name: consumer.name, private: true, type: 'module' }, null, 2)); + + for (const [file, contents] of Object.entries(consumer.files)) writeFileSync(join(dir, file), contents); + + const needsTypeScript = consumer.name.startsWith('ts-'); + + try { + run('npm', ['install', '--no-audit', '--no-fund', '--silent', tarball, ...(needsTypeScript ? ['typescript', '@types/node'] : [])], dir); + + const [command, args] = consumer.verify(dir); + + run(command, args, dir); + console.log(`✅ ${consumer.name}`); + } catch (error) { + failures += 1; + const details = error as { stdout?: string; stderr?: string; message: string }; + console.error(`❌ ${consumer.name}\n${details.stdout || ''}${details.stderr || details.message}`); + } + } +} finally { + rmSync(workspace, { recursive: true, force: true }); +} + +if (failures) { + console.error(`\n${failures} consumer check(s) failed — the published package would be broken for them.`); + process.exit(1); +} + +console.log('\nAll consumers can install and use the packed package.'); diff --git a/scripts/checkBrowser.ts b/scripts/checkBrowser.ts new file mode 100644 index 00000000..a358d8de --- /dev/null +++ b/scripts/checkBrowser.ts @@ -0,0 +1,131 @@ +/** + * Runs the built package inside a real browser. + * + * The static gate (scripts/checkBrowserSafe.ts) proves nothing Node-only is *mentioned*. This proves the package + * actually loads and works: modules evaluate, a request goes out with the right auth header, a failure arrives as a + * typed error, and an attachment is encoded as multipart the server can parse. + * + * Both shipping shapes are covered, because they fail differently: + * + * - `dist/browser.js`, the self-contained bundle, which must work with no resolver at all; + * - `dist/index.js`, which imports `zod` by bare specifier and stands in for a dependency-resolving CDN — here an + * import map does the resolving that esm.sh or jsDelivr would do. + * + * Runs on bare `node`; keep the types erasable. + */ +import { createServer } from 'node:http'; +import type { IncomingMessage, ServerResponse } from 'node:http'; +import { createReadStream, existsSync } from 'node:fs'; +import { dirname, join, resolve } from 'node:path'; +import { fileURLToPath } from 'node:url'; +import { chromium } from 'playwright'; + +const root = resolve(dirname(fileURLToPath(import.meta.url)), '..'); + +const MIME: Record = { + '.js': 'text/javascript', + '.map': 'application/json', + '.html': 'text/html', +}; + +type Recorded = { url: string; method: string; auth: string | undefined; contentType: string | undefined; body: string }; + +const recorded: Recorded[] = []; + +function send(res: ServerResponse, status: number, body: string, type = 'application/json'): void { + res.writeHead(status, { + 'content-type': type, + 'access-control-allow-origin': '*', + 'access-control-allow-headers': '*', + }); + res.end(body); +} + +const server = createServer((req: IncomingMessage, res: ServerResponse) => { + const url = new URL(req.url ?? '/', 'http://localhost'); + + if (req.method === 'OPTIONS') return send(res, 204, ''); + + // Static: the built package and the harness page. + if (!url.pathname.startsWith('/wiki/')) { + const file = url.pathname === '/' ? '/harness.html' : url.pathname; + const onDisk = file === '/harness.html' ? join(root, 'scripts', 'browserHarness.html') : join(root, file); + + if (!existsSync(onDisk)) return send(res, 404, 'not found', 'text/plain'); + + const ext = onDisk.slice(onDisk.lastIndexOf('.')); + + res.writeHead(200, { 'content-type': MIME[ext] ?? 'application/octet-stream' }); + + return void createReadStream(onDisk).pipe(res); + } + + // API: record what arrived, then answer as Confluence would. + const chunks: Uint8Array[] = []; + + req.on('data', chunk => chunks.push(chunk as Uint8Array)); + req.on('end', () => { + recorded.push({ + url: url.pathname, + method: req.method ?? '', + auth: req.headers.authorization, + contentType: req.headers['content-type'], + body: Buffer.concat(chunks).toString('utf8'), + }); + + if (url.pathname.endsWith('/missing')) { + return send(res, 404, JSON.stringify({ message: 'No page with id' })); + } + + if (url.pathname.includes('/attachment')) { + return send(res, 200, JSON.stringify({ results: [{ id: 'att1' }] })); + } + + send(res, 200, JSON.stringify({ results: [{ id: '1', title: 'Page' }], _links: {} })); + }); +}); + +await new Promise(done => server.listen(0, () => done())); + +const port = (server.address() as { port: number }).port; +const origin = `http://localhost:${port}`; + +const browser = await chromium.launch(); +const page = await browser.newPage(); +const consoleErrors: string[] = []; + +page.on('pageerror', error => consoleErrors.push(String(error))); + +await page.goto(`${origin}/?port=${port}`); + +const results = (await page.evaluate('window.__run()')) as { name: string; ok: boolean; detail: string }[]; + +await browser.close(); +server.close(); + +let failed = 0; + +for (const result of results) { + console.log(`${result.ok ? ' PASS' : ' FAIL'} ${result.name}${result.detail ? ` — ${result.detail}` : ''}`); + if (!result.ok) failed += 1; +} + +for (const error of consoleErrors) { + console.log(` FAIL uncaught in page — ${error}`); + failed += 1; +} + +// A harness that silently ran nothing would otherwise report success. +if (results.length === 0) { + console.log(' FAIL the harness reported no results at all'); + failed += 1; +} + +console.log(''); + +if (failed > 0) { + console.error(`✖ ${failed} browser check(s) failed`); + process.exit(1); +} + +console.log(`✔ browser: ${results.length} checks passed in Chromium`); diff --git a/scripts/checkBrowserSafe.ts b/scripts/checkBrowserSafe.ts new file mode 100644 index 00000000..0cb40ff4 --- /dev/null +++ b/scripts/checkBrowserSafe.ts @@ -0,0 +1,130 @@ +/** + * Proves the built package can run in a browser. + * + * Two failures have already shipped past review here, and each is cheap to catch mechanically: + * + * - a runtime reference to `process` or a `node:` import, which breaks the moment the bundle is loaded — `process` is + * the worse of the two, because bundlers shim it as an empty object and the crash is a TypeError deep inside a + * property read rather than a missing-module error; + * - a Node type such as `Buffer` or `node:stream` leaking into the shipped declarations, which breaks `tsc` for every + * browser consumer that does not install `@types/node`. + * + * Runs on bare `node` — keep the types here erasable, as in scripts/devVersion.ts. + */ +import { execFileSync } from 'node:child_process'; +import { mkdirSync, readFileSync, readdirSync, rmSync, writeFileSync } from 'node:fs'; +import { dirname, join, relative, resolve } from 'node:path'; +import { fileURLToPath } from 'node:url'; + +const root = resolve(dirname(fileURLToPath(import.meta.url)), '..'); +const dist = join(root, 'dist'); + +function walk(dir: string, ext: string): string[] { + const found: string[] = []; + + for (const entry of readdirSync(dir, { withFileTypes: true })) { + const full = join(dir, entry.name); + + if (entry.isDirectory()) found.push(...walk(full, ext)); + else if (entry.name.endsWith(ext)) found.push(full); + } + + return found; +} + +const problems: string[] = []; + +// The browser bundle is exempt from the runtime scan: it inlines dependencies, +// and a dependency may legitimately carry a guarded `process` reference. +const runtimeFiles = walk(dist, '.js').filter(file => !file.endsWith('browser.js')); + +const RUNTIME_PATTERNS = [ + { label: 'a node: import', regex: /(?:from|import)\s*\(?\s*['"]node:/ }, + { label: 'a require() call', regex: /\brequire\s*\(/ }, + { label: 'a process reference', regex: /\bprocess\s*\./ }, + { label: 'a Buffer reference', regex: /\bBuffer\b/ }, +]; + +/** Comments mention `Buffer` and `process` precisely because the code avoids them; only executable text counts. */ +function stripComments(source: string): string { + return source.replace(/\/\*[\s\S]*?\*\//g, match => match.replace(/[^\n]/g, ' ')).replace(/\/\/[^\n]*/g, ''); +} + +for (const file of runtimeFiles) { + const source = stripComments(readFileSync(file, 'utf8')); + + for (const { label, regex } of RUNTIME_PATTERNS) { + const lines = source.split('\n'); + + lines.forEach((line, index) => { + if (regex.test(line)) { + problems.push(`${relative(root, file)}:${index + 1} — ${label}: ${line.trim()}`); + } + }); + } +} + +// Compile every published entry point the way a browser project would: DOM libs, +// no ambient Node types at all. +const probe = join(root, 'node_modules', '.cache', 'browser-safe'); + +rmSync(probe, { recursive: true, force: true }); +mkdirSync(join(probe, 'src'), { recursive: true }); + +const entries = ['.', './core', './v1', './v2']; +const pkg = JSON.parse(readFileSync(join(root, 'package.json'), 'utf8')); + +writeFileSync( + join(probe, 'src', 'index.ts'), + entries + .map((entry, index) => { + const target = entry === '.' ? pkg.exports['.'].types : pkg.exports[entry].types; + + return `import * as e${index} from '${join(root, target).replace(/\.d\.ts$/, '.js')}';\nvoid e${index};`; + }) + .join('\n'), +); + +writeFileSync( + join(probe, 'tsconfig.json'), + JSON.stringify( + { + compilerOptions: { + target: 'ES2022', + module: 'ESNext', + moduleResolution: 'bundler', + lib: ['ES2022', 'DOM', 'DOM.Iterable'], + types: [], // the whole point: no @types/node + strict: true, + noEmit: true, + skipLibCheck: false, + }, + include: ['src'], + }, + null, + 2, + ), +); + +try { + execFileSync(join(root, 'node_modules', '.bin', 'tsc'), ['--project', probe], { + encoding: 'utf8', + stdio: 'pipe', + }); +} catch (error) { + const { stdout, stderr, message } = error as { stdout?: string; stderr?: string; message?: string }; + const output = `${stdout ?? ''}${stderr ?? ''}`.trim() || message || 'tsc failed without output'; + + problems.push(`the shipped declarations need @types/node:\n${output}`); +} + +rmSync(probe, { recursive: true, force: true }); + +if (problems.length > 0) { + console.error(`✖ ${problems.length} browser-compatibility problem(s):\n`); + for (const problem of problems) console.error(` ${problem}`); + console.error(''); + process.exit(1); +} + +console.log(`✔ browser-safe: ${runtimeFiles.length} runtime files clean, ${entries.length} entry points typecheck`); diff --git a/scripts/devVersion.ts b/scripts/devVersion.ts new file mode 100644 index 00000000..d2c3f4de --- /dev/null +++ b/scripts/devVersion.ts @@ -0,0 +1,67 @@ +/** + * Stamps the version of a dev-channel snapshot. + * + * Run after `changeset version`, which has already moved package.json to the + * version this branch would release. This turns that into `-dev.`, + * where n comes from the registry: the highest `-dev.*` already published, + * plus one. npm is the source of truth, so nothing has to be committed back and + * the script works from any branch. + * + * Runs on bare `node` — the types here are erasable, so Node strips them without + * a compile step. Keep it that way: no enums, no namespaces, no parameter + * properties, or it stops being runnable. + * + * Run: pnpm run version:dev + */ +import { execFileSync } from 'node:child_process'; +import { readFileSync, writeFileSync } from 'node:fs'; +import { resolve } from 'node:path'; + +const packagePath = resolve(import.meta.dirname, '..', 'package.json'); +const manifest = JSON.parse(readFileSync(packagePath, 'utf8')) as { name: string; version: string }; + +/** Every version of this package on npm, or [] if it has never been published. */ +function publishedVersions(name: string): string[] { + try { + const stdout = execFileSync('npm', ['view', name, 'versions', '--json'], { + encoding: 'utf8', + stdio: ['ignore', 'pipe', 'pipe'], + }); + const parsed: unknown = JSON.parse(stdout); + + // A single-release package comes back as a bare string, not an array. + return Array.isArray(parsed) ? (parsed as string[]) : [String(parsed)]; + } catch { + return []; + } +} + +/** + * The release this snapshot leads to. + * + * With changesets pending, `changeset version` has already bumped package.json + * and that is the answer. With none pending the version still names the last + * release, and if it is already on npm the snapshot would sort *below* it — so + * take the next patch instead. + */ +function baseVersion(current: string, published: string[]): string { + if (!published.includes(current)) return current; + + const [major, minor, patch] = current.split('.').map(Number); + + return `${major}.${minor}.${patch + 1}`; +} + +const published = publishedVersions(manifest.name); +const base = baseVersion(manifest.version, published); + +const counter = published + .map(version => new RegExp(`^${base.replaceAll('.', '\\.')}-dev\\.(\\d+)$`).exec(version)) + .filter(match => match !== null) + .reduce((highest, match) => Math.max(highest, Number(match[1]) + 1), 0); + +manifest.version = `${base}-dev.${counter}`; + +writeFileSync(packagePath, `${JSON.stringify(manifest, null, 2)}\n`); + +console.log(manifest.version); diff --git a/scripts/prepare-api-docs.ts b/scripts/prepare-api-docs.ts new file mode 100644 index 00000000..d68cefc1 --- /dev/null +++ b/scripts/prepare-api-docs.ts @@ -0,0 +1,115 @@ +/** + * Post-processes the TypeDoc output for VitePress. Runs as part of `docs:api`. + * + * Three jobs: + * + * 1. **Escape stray `<` in prose.** VitePress compiles every markdown file as a + * Vue template, and Atlassian's endpoint descriptions carry raw markup and + * placeholders — ``, ``, an unclosed `
`. Vue reads
+ *    those as elements and the build dies on "Element is missing end tag".
+ *
+ * 2. **Trim the sidebar.** TypeDoc lists every page it writes, and `models` +
+ *    `parameters` are the bulk of them — VitePress embeds the whole tree into
+ *    every page's hydration state, so leaving them in inflates each HTML file by
+ *    hundreds of kilobytes. They stay reachable: every function signature links
+ *    to the types it uses. Only the navigation tree drops them.
+ *
+ * 3. **Mirror the reference under `/ru/api/`.** The reference itself is
+ *    English (it comes from Atlassian's own descriptions), but VitePress's
+ *    language switcher rewrites `/api/*` → `/ru/api/*`, so the route has to
+ *    resolve. `hreflang` marks the two as the same page. The RU sidebar is the
+ *    same tree with its links re-prefixed, so navigating inside the reference
+ *    keeps you in the locale you chose.
+ */
+import { cpSync, existsSync, readFileSync, rmSync, writeFileSync } from 'node:fs';
+import { dirname, relative, resolve } from 'node:path';
+import { fileURLToPath } from 'node:url';
+import { glob } from 'node:fs/promises';
+
+const root = resolve(dirname(fileURLToPath(import.meta.url)), '..');
+const apiDir = resolve(root, 'docs/api');
+const ruApiDir = resolve(root, 'docs/ru/api');
+const sidebarPath = resolve(apiDir, 'typedoc-sidebar.json');
+const ruSidebarPath = resolve(apiDir, 'typedoc-sidebar.ru.json');
+
+/** Sidebar groups that are reachable by link but too numerous to navigate. */
+const EXCLUDED_GROUPS = new Set(['models', 'parameters']);
+
+interface SidebarEntry {
+  text?: string;
+  link?: string;
+  items?: SidebarEntry[];
+}
+
+if (!existsSync(apiDir)) {
+  console.error(`[prepare-api-docs] no TypeDoc output at ${relative(root, apiDir)} — run \`pnpm docs:api\` first.`);
+  process.exit(1);
+}
+
+/** Drop the excluded groups wherever they sit: they are nested under v1/v2, not top-level. */
+function trim(entries: SidebarEntry[]): SidebarEntry[] {
+  return entries
+    .filter(entry => !(entry.text && EXCLUDED_GROUPS.has(entry.text)))
+    .map(entry => (entry.items ? { ...entry, items: trim(entry.items) } : entry));
+}
+
+function count(entries: SidebarEntry[]): number {
+  return entries.reduce((total, entry) => total + 1 + (entry.items ? count(entry.items) : 0), 0);
+}
+
+/** Stand-in for a parked code span. U+0000 cannot occur in the markdown TypeDoc emits. */
+const SENTINEL = '\u0000';
+
+/**
+ * Escape `<` everywhere Vue would read it as a tag: outside fenced blocks and
+ * outside inline code. `>` is left alone — it is harmless on its own, and
+ * escaping it would eat blockquote markers.
+ */
+function escapeProseAngleBrackets(markdown: string): string {
+  let inFence = false;
+
+  return markdown
+    .split('\n')
+    .map(line => {
+      if (/^\s*```/.test(line)) {
+        inFence = !inFence;
+
+        return line;
+      }
+
+      if (inFence || !line.includes('<')) return line;
+
+      const spans: string[] = [];
+      const masked = line.replace(/`[^`]*`/g, span => `${SENTINEL}${spans.push(span) - 1}${SENTINEL}`);
+
+      return masked
+        .replace(/ spans[Number(index)]);
+    })
+    .join('\n');
+}
+
+let escapedFiles = 0;
+
+for await (const file of glob(`${apiDir}/**/*.md`)) {
+  const original = readFileSync(file, 'utf8');
+  const escaped = escapeProseAngleBrackets(original);
+
+  if (escaped !== original) {
+    writeFileSync(file, escaped);
+    escapedFiles += 1;
+  }
+}
+
+const sidebar = JSON.parse(readFileSync(sidebarPath, 'utf8')) as SidebarEntry[];
+const trimmed = trim(sidebar);
+
+writeFileSync(sidebarPath, JSON.stringify(trimmed));
+writeFileSync(ruSidebarPath, JSON.stringify(trimmed).replaceAll('"/api/', '"/ru/api/'));
+
+if (existsSync(ruApiDir)) rmSync(ruApiDir, { recursive: true, force: true });
+cpSync(apiDir, ruApiDir, { recursive: true });
+
+console.log(`[prepare-api-docs] escaped stray markup in ${escapedFiles} page(s)`);
+console.log(`[prepare-api-docs] sidebar ${count(sidebar)} → ${count(trimmed)} entries (models, parameters dropped)`);
+console.log(`[prepare-api-docs] mirrored ${relative(root, apiDir)} → ${relative(root, ruApiDir)}`);
diff --git a/src/api/analytics.ts b/src/api/analytics.ts
deleted file mode 100644
index 4a279487..00000000
--- a/src/api/analytics.ts
+++ /dev/null
@@ -1,44 +0,0 @@
-import type * as Models from './models';
-import type * as Parameters from './parameters';
-import type { Client } from '../clients';
-import type { Callback } from '../callback';
-import type { RequestConfig } from '../requestConfig';
-
-export class Analytics {
-  constructor(private client: Client) {}
-
-  /** Get the total number of views a piece of content has. */
-  async getViews(parameters: Parameters.GetViews, callback: Callback): Promise;
-  /** Get the total number of views a piece of content has. */
-  async getViews(parameters: Parameters.GetViews, callback?: never): Promise;
-  async getViews(parameters: Parameters.GetViews, callback?: Callback): Promise {
-    const config: RequestConfig = {
-      url: `/api/analytics/content/${parameters.contentId}/views`,
-      method: 'GET',
-      params: {
-        fromDate: parameters.fromDate,
-      },
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-
-  /** Get the total number of distinct viewers a piece of content has. */
-  async getViewers(parameters: Parameters.GetViewers, callback: Callback): Promise;
-  /** Get the total number of distinct viewers a piece of content has. */
-  async getViewers(parameters: Parameters.GetViewers, callback?: never): Promise;
-  async getViewers(
-    parameters: Parameters.GetViewers,
-    callback?: Callback,
-  ): Promise {
-    const config: RequestConfig = {
-      url: `/api/analytics/content/${parameters.contentId}/viewers`,
-      method: 'GET',
-      params: {
-        fromDate: parameters.fromDate,
-      },
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-}
diff --git a/src/api/audit.ts b/src/api/audit.ts
deleted file mode 100644
index 7d20efd9..00000000
--- a/src/api/audit.ts
+++ /dev/null
@@ -1,241 +0,0 @@
-import type * as Models from './models';
-import type * as Parameters from './parameters';
-import type { Client } from '../clients';
-import type { Callback } from '../callback';
-import type { RequestConfig } from '../requestConfig';
-
-export class Audit {
-  constructor(private client: Client) {}
-
-  /**
-   * Returns all records in the audit log, optionally for a certain date range. This contains information about events
-   * like space exports, group membership changes, app installations, etc. For more information, see [Audit
-   * log](https://confluence.atlassian.com/confcloud/audit-log-802164269.html) in the Confluence administrator's guide.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'Confluence Administrator' global
-   * permission.
-   */
-  async getAuditRecords(
-    parameters: Parameters.GetAuditRecords | undefined,
-    callback: Callback,
-  ): Promise;
-  /**
-   * Returns all records in the audit log, optionally for a certain date range. This contains information about events
-   * like space exports, group membership changes, app installations, etc. For more information, see [Audit
-   * log](https://confluence.atlassian.com/confcloud/audit-log-802164269.html) in the Confluence administrator's guide.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'Confluence Administrator' global
-   * permission.
-   */
-  async getAuditRecords(
-    parameters?: Parameters.GetAuditRecords,
-    callback?: never,
-  ): Promise;
-  async getAuditRecords(
-    parameters?: Parameters.GetAuditRecords,
-    callback?: Callback,
-  ): Promise {
-    const config: RequestConfig = {
-      url: '/api/audit',
-      method: 'GET',
-      params: {
-        startDate: parameters?.startDate,
-        endDate: parameters?.endDate,
-        searchString: parameters?.searchString,
-        start: parameters?.start,
-        limit: parameters?.limit,
-      },
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-
-  /**
-   * Creates a record in the audit log.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'Confluence Administrator' global
-   * permission.
-   */
-  async createAuditRecord(
-    parameters: Parameters.CreateAuditRecord | undefined,
-    callback: Callback,
-  ): Promise;
-  /**
-   * Creates a record in the audit log.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'Confluence Administrator' global
-   * permission.
-   */
-  async createAuditRecord(
-    parameters?: Parameters.CreateAuditRecord,
-    callback?: never,
-  ): Promise;
-  async createAuditRecord(
-    parameters?: Parameters.CreateAuditRecord,
-    callback?: Callback,
-  ): Promise {
-    const config: RequestConfig = {
-      url: '/api/audit',
-      method: 'POST',
-      data: {
-        author: parameters?.author,
-        remoteAddress: parameters?.remoteAddress,
-        creationDate: parameters?.creationDate,
-        summary: parameters?.summary,
-        description: parameters?.description,
-        category: parameters?.category,
-        sysAdmin: parameters?.sysAdmin,
-        affectedObject: parameters?.affectedObject,
-        changedValues: parameters?.changedValues,
-        associatedObjects: parameters?.associatedObjects,
-      },
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-
-  /**
-   * Exports audit records as a CSV file or ZIP file.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'Confluence Administrator' global
-   * permission.
-   */
-  async exportAuditRecords(
-    parameters: Parameters.ExportAuditRecords | undefined,
-    callback: Callback,
-  ): Promise;
-  /**
-   * Exports audit records as a CSV file or ZIP file.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'Confluence Administrator' global
-   * permission.
-   */
-  async exportAuditRecords(parameters?: Parameters.ExportAuditRecords, callback?: never): Promise;
-  async exportAuditRecords(
-    parameters?: Parameters.ExportAuditRecords,
-    callback?: Callback,
-  ): Promise {
-    const config: RequestConfig = {
-      url: '/api/audit/export',
-      method: 'GET',
-      params: {
-        startDate: parameters?.startDate,
-        endDate: parameters?.endDate,
-        searchString: parameters?.searchString,
-        format: parameters?.format,
-      },
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-
-  /**
-   * Returns the retention period for records in the audit log. The retention period is how long an audit record is kept
-   * for, from creation date until it is deleted.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'Confluence Administrator' global
-   * permission.
-   */
-  async getRetentionPeriod(callback: Callback): Promise;
-  /**
-   * Returns the retention period for records in the audit log. The retention period is how long an audit record is kept
-   * for, from creation date until it is deleted.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'Confluence Administrator' global
-   * permission.
-   */
-  async getRetentionPeriod(callback?: never): Promise;
-  async getRetentionPeriod(callback?: Callback): Promise {
-    const config: RequestConfig = {
-      url: '/api/audit/retention',
-      method: 'GET',
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-
-  /**
-   * Sets the retention period for records in the audit log. The retention period can be set to a maximum of 1 year.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'Confluence Administrator' global
-   * permission.
-   */
-  async setRetentionPeriod(
-    parameters: Parameters.SetRetentionPeriod | undefined,
-    callback: Callback,
-  ): Promise;
-  /**
-   * Sets the retention period for records in the audit log. The retention period can be set to a maximum of 1 year.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'Confluence Administrator' global
-   * permission.
-   */
-  async setRetentionPeriod(
-    parameters?: Parameters.SetRetentionPeriod,
-    callback?: never,
-  ): Promise;
-  async setRetentionPeriod(
-    parameters?: Parameters.SetRetentionPeriod,
-    callback?: Callback,
-  ): Promise {
-    const config: RequestConfig = {
-      url: '/api/audit/retention',
-      method: 'PUT',
-      data: {
-        number: parameters?.number,
-        units: parameters?.units,
-      },
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-
-  /**
-   * Returns records from the audit log, for a time period back from the current date. For example, you can use this
-   * method to get the last 3 months of records.
-   *
-   * This contains information about events like space exports, group membership changes, app installations, etc. For
-   * more information, see [Audit log](https://confluence.atlassian.com/confcloud/audit-log-802164269.html) in the
-   * Confluence administrator's guide.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'Confluence Administrator' global
-   * permission.
-   */
-  async getAuditRecordsForTimePeriod(
-    parameters: Parameters.GetAuditRecordsForTimePeriod | undefined,
-    callback: Callback,
-  ): Promise;
-  /**
-   * Returns records from the audit log, for a time period back from the current date. For example, you can use this
-   * method to get the last 3 months of records.
-   *
-   * This contains information about events like space exports, group membership changes, app installations, etc. For
-   * more information, see [Audit log](https://confluence.atlassian.com/confcloud/audit-log-802164269.html) in the
-   * Confluence administrator's guide.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'Confluence Administrator' global
-   * permission.
-   */
-  async getAuditRecordsForTimePeriod(
-    parameters?: Parameters.GetAuditRecordsForTimePeriod,
-    callback?: never,
-  ): Promise;
-  async getAuditRecordsForTimePeriod(
-    parameters?: Parameters.GetAuditRecordsForTimePeriod,
-    callback?: Callback,
-  ): Promise {
-    const config: RequestConfig = {
-      url: '/api/audit/since',
-      method: 'GET',
-      params: {
-        number: parameters?.number,
-        units: parameters?.units,
-        searchString: parameters?.searchString,
-        start: parameters?.start,
-        limit: parameters?.limit,
-      },
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-}
diff --git a/src/api/content.ts b/src/api/content.ts
deleted file mode 100644
index 86fb8106..00000000
--- a/src/api/content.ts
+++ /dev/null
@@ -1,467 +0,0 @@
-import type * as Models from './models';
-import type * as Parameters from './parameters';
-import type { Client } from '../clients';
-import type { Callback } from '../callback';
-import type { RequestConfig } from '../requestConfig';
-
-export class Content {
-  constructor(private client: Client) {}
-
-  /**
-   * Returns all content in a Confluence instance.
-   *
-   * By default, the following objects are expanded: `space`, `history`, `version`.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to access the Confluence site
-   * ('Can use' global permission). Only content that the user has permission to view will be returned.
-   *
-   * @deprecated Will be removed in next major version.
-   */
-  async getContent(
-    parameters: Parameters.GetContent | undefined,
-    callback: Callback,
-  ): Promise;
-  /**
-   * Returns all content in a Confluence instance.
-   *
-   * By default, the following objects are expanded: `space`, `history`, `version`.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to access the Confluence site
-   * ('Can use' global permission). Only content that the user has permission to view will be returned.
-   *
-   * @deprecated Will be removed in next major version.
-   */
-  async getContent(parameters?: Parameters.GetContent, callback?: never): Promise;
-  async getContent(
-    parameters?: Parameters.GetContent,
-    callback?: Callback,
-  ): Promise {
-    const config: RequestConfig = {
-      url: '/api/content',
-      method: 'GET',
-      params: {
-        type: parameters?.type,
-        spaceKey: parameters?.spaceKey,
-        title: parameters?.title,
-        status: parameters?.status,
-        postingDay: parameters?.postingDay,
-        trigger: parameters?.trigger,
-        orderby: parameters?.orderby,
-        start: parameters?.start,
-        limit: parameters?.limit,
-        expand: parameters?.expand,
-      },
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-
-  /**
-   * Creates a new piece of content or publishes an existing draft.
-   *
-   * To publish a draft, add the `id` and `status` properties to the body of the request. Set the `id` to the ID of the
-   * draft and set the `status` to 'current'. When the request is sent, a new piece of content will be created and the
-   * metadata from the draft will be transferred into it.
-   *
-   * By default, the following objects are expanded: `space`, `history`, `version`.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'Add' permission for the space that the
-   * content will be created in, and permission to view the draft if publishing a draft.
-   *
-   * @deprecated Will be removed in next major version.
-   */
-  async createContent(
-    parameters: Parameters.CreateContent | undefined,
-    callback: Callback,
-  ): Promise;
-  /**
-   * Creates a new piece of content or publishes an existing draft.
-   *
-   * To publish a draft, add the `id` and `status` properties to the body of the request. Set the `id` to the ID of the
-   * draft and set the `status` to 'current'. When the request is sent, a new piece of content will be created and the
-   * metadata from the draft will be transferred into it.
-   *
-   * By default, the following objects are expanded: `space`, `history`, `version`.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'Add' permission for the space that the
-   * content will be created in, and permission to view the draft if publishing a draft.
-   *
-   * @deprecated Will be removed in next major version.
-   */
-  async createContent(parameters?: Parameters.CreateContent, callback?: never): Promise;
-  async createContent(
-    parameters?: Parameters.CreateContent,
-    callback?: Callback,
-  ): Promise {
-    const config: RequestConfig = {
-      url: '/api/content',
-      method: 'POST',
-      params: {
-        status: parameters?.status,
-        expand: parameters?.expand,
-      },
-      data: {
-        ...parameters,
-        status: undefined,
-        expand: undefined,
-      },
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-
-  /**
-   * Archives a list of pages. The pages to be archived are specified as a list of content IDs. This API accepts the
-   * archival request and returns a task ID. The archival process happens asynchronously. Use the /longtask/
-   * REST API to get the copy task status.
-   *
-   * Each content ID needs to resolve to page objects that are not already in an archived state. The content IDs need
-   * not belong to the same space.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'Archive' permission for each of the pages
-   * in the corresponding space it belongs to.
-   */
-  async archivePages(parameters: Parameters.ArchivePages, callback: Callback): Promise;
-  /**
-   * Archives a list of pages. The pages to be archived are specified as a list of content IDs. This API accepts the
-   * archival request and returns a task ID. The archival process happens asynchronously. Use the /longtask/
-   * REST API to get the copy task status.
-   *
-   * Each content ID needs to resolve to page objects that are not already in an archived state. The content IDs need
-   * not belong to the same space.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'Archive' permission for each of the pages
-   * in the corresponding space it belongs to.
-   */
-  async archivePages(parameters: Parameters.ArchivePages, callback?: never): Promise;
-  async archivePages(
-    parameters: Parameters.ArchivePages,
-    callback?: Callback,
-  ): Promise {
-    const config: RequestConfig = {
-      url: '/api/content/archive',
-      method: 'POST',
-      data: {
-        pages: parameters.pages,
-      },
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-
-  /**
-   * Publishes a legacy draft of a page created from a blueprint. Legacy drafts will eventually be removed in favor of
-   * shared drafts. For now, this method works the same as [Publish shared
-   * draft](#api-content-blueprint-instance-draftId-put).
-   *
-   * By default, the following objects are expanded: `body.storage`, `history`, `space`, `version`, `ancestors`.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to view the draft and 'Add'
-   * permission for the space that the content will be created in.
-   */
-  async publishLegacyDraft(
-    parameters: Parameters.PublishLegacyDraft,
-    callback: Callback,
-  ): Promise;
-  /**
-   * Publishes a legacy draft of a page created from a blueprint. Legacy drafts will eventually be removed in favor of
-   * shared drafts. For now, this method works the same as [Publish shared
-   * draft](#api-content-blueprint-instance-draftId-put).
-   *
-   * By default, the following objects are expanded: `body.storage`, `history`, `space`, `version`, `ancestors`.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to view the draft and 'Add'
-   * permission for the space that the content will be created in.
-   */
-  async publishLegacyDraft(parameters: Parameters.PublishLegacyDraft, callback?: never): Promise;
-  async publishLegacyDraft(
-    parameters: Parameters.PublishLegacyDraft,
-    callback?: Callback,
-  ): Promise {
-    const config: RequestConfig = {
-      url: `/api/content/blueprint/instance/${parameters.draftId}`,
-      method: 'POST',
-      params: {
-        status: parameters.status,
-      },
-      data: {
-        ...parameters,
-        version: parameters.version,
-        title: parameters.title,
-        type: parameters.type,
-        status: parameters.bodyStatus,
-        space: parameters.space,
-        ancestors: parameters.ancestors,
-      },
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-
-  /**
-   * Publishes a shared draft of a page created from a blueprint.
-   *
-   * By default, the following objects are expanded: `body.storage`, `history`, `space`, `version`, `ancestors`.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to view the draft and 'Add'
-   * permission for the space that the content will be created in.
-   */
-  async publishSharedDraft(
-    parameters: Parameters.PublishSharedDraft,
-    callback: Callback,
-  ): Promise;
-  /**
-   * Publishes a shared draft of a page created from a blueprint.
-   *
-   * By default, the following objects are expanded: `body.storage`, `history`, `space`, `version`, `ancestors`.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to view the draft and 'Add'
-   * permission for the space that the content will be created in.
-   */
-  async publishSharedDraft(parameters: Parameters.PublishSharedDraft, callback?: never): Promise;
-  async publishSharedDraft(
-    parameters: Parameters.PublishSharedDraft,
-    callback?: Callback,
-  ): Promise {
-    const config: RequestConfig = {
-      url: `/api/content/blueprint/instance/${parameters.draftId}`,
-      method: 'PUT',
-      params: {
-        status: parameters.status,
-      },
-      data: {
-        ...parameters,
-        status: parameters.bodyStatus,
-      },
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-
-  /**
-   * Returns the list of content that matches a Confluence Query Language (CQL) query. For information on CQL, see:
-   * [Advanced searching using CQL](https://developer.atlassian.com/cloud/confluence/advanced-searching-using-cql/).
-   *
-   * When additional results are available, returns `next` and `prev` URLs to retrieve them in subsequent calls. The
-   * URLs each contain a cursor that points to the appropriate set of results. Use `limit` to specify the number of
-   * results returned in each call.
-   *
-   * The response to this will have a `prev` URL similar to the `next` in the example response.
-   *
-   * If the expand query parameter is used with the `body.export_view` and/or `body.styled_view` properties, then the
-   * query limit parameter will be restricted to a maximum value of 25.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to access the Confluence site
-   * ('Can use' global permission). Only content that the user has permission to view will be returned.
-   */
-  async searchContentByCQL(
-    parameters: Parameters.SearchContentByCQL,
-    callback: Callback,
-  ): Promise;
-  /**
-   * Returns the list of content that matches a Confluence Query Language (CQL) query. For information on CQL, see:
-   * [Advanced searching using CQL](https://developer.atlassian.com/cloud/confluence/advanced-searching-using-cql/).
-   *
-   * When additional results are available, returns `next` and `prev` URLs to retrieve them in subsequent calls. The
-   * URLs each contain a cursor that points to the appropriate set of results. Use `limit` to specify the number of
-   * results returned in each call.
-   *
-   * The response to this will have a `prev` URL similar to the `next` in the example response.
-   *
-   * If the expand query parameter is used with the `body.export_view` and/or `body.styled_view` properties, then the
-   * query limit parameter will be restricted to a maximum value of 25.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to access the Confluence site
-   * ('Can use' global permission). Only content that the user has permission to view will be returned.
-   */
-  async searchContentByCQL(
-    parameters: Parameters.SearchContentByCQL,
-    callback?: never,
-  ): Promise;
-  async searchContentByCQL(
-    parameters: Parameters.SearchContentByCQL,
-    callback?: Callback,
-  ): Promise {
-    const config: RequestConfig = {
-      url: '/api/content/search',
-      method: 'GET',
-      params: {
-        cql: parameters.cql,
-        cqlcontext: parameters.cqlcontext,
-        cursor: parameters.cursor,
-        limit: parameters.limit,
-        expand: parameters.expand,
-      },
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-
-  /**
-   * Returns a single piece of content, like a page or a blog post.
-   *
-   * By default, the following objects are expanded: `space`, `history`, `version`.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to view the content. If the
-   * content is a blog post, 'View' permission for the space is required.
-   *
-   * @deprecated Will be removed in next major version.
-   */
-  async getContentById(parameters: Parameters.GetContentById, callback: Callback): Promise;
-  /**
-   * Returns a single piece of content, like a page or a blog post.
-   *
-   * By default, the following objects are expanded: `space`, `history`, `version`.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to view the content. If the
-   * content is a blog post, 'View' permission for the space is required.
-   *
-   * @deprecated Will be removed in next major version.
-   */
-  async getContentById(parameters: Parameters.GetContentById, callback?: never): Promise;
-  async getContentById(
-    parameters: Parameters.GetContentById,
-    callback?: Callback,
-  ): Promise {
-    const config: RequestConfig = {
-      url: `/api/content/${parameters.id}`,
-      method: 'GET',
-      params: {
-        status: parameters.status,
-        version: parameters.version,
-        embeddedContentRender: parameters.embeddedContentRender,
-        trigger: parameters.trigger,
-        expand: parameters.expand,
-      },
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-
-  /**
-   * Updates a piece of content. Use this method to update the title or body of a piece of content, change the status,
-   * change the parent page, and more.
-   *
-   * Note, updating draft content is currently not supported.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to update the content.
-   *
-   * @deprecated Will be removed in next major version.
-   */
-  async updateContent(parameters: Parameters.UpdateContent, callback: Callback): Promise;
-  /**
-   * Updates a piece of content. Use this method to update the title or body of a piece of content, change the status,
-   * change the parent page, and more.
-   *
-   * Note, updating draft content is currently not supported.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to update the content.
-   *
-   * @deprecated Will be removed in next major version.
-   */
-  async updateContent(parameters: Parameters.UpdateContent, callback?: never): Promise;
-  async updateContent(
-    parameters: Parameters.UpdateContent,
-    callback?: Callback,
-  ): Promise {
-    const config: RequestConfig = {
-      url: `/api/content/${parameters.id}`,
-      method: 'PUT',
-      params: {
-        status: parameters.status,
-        conflictPolicy: parameters.conflictPolicy,
-      },
-      data: {
-        version: parameters.version,
-        title: parameters.title,
-        type: parameters.type,
-        status: parameters.statusBody,
-        ancestors: parameters.ancestors,
-        body: parameters.body,
-      },
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-
-  /**
-   * Moves a piece of content to the space's trash or purges it from the trash, depending on the content's type and
-   * status:
-   *
-   * - If the content's type is `page` or `blogpost` and its status is `current`, it will be trashed.
-   * - If the content's type is `page` or `blogpost` and its status is `trashed`, the content will be purged from the
-   *   trash and deleted permanently. Note, you must also set the `status` query parameter to `trashed` in your
-   *   request.
-   * - If the content's type is `comment` or `attachment`, it will be deleted permanently without being trashed.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'Delete' permission for the space that the
-   * content is in.
-   *
-   * @deprecated Will be removed in next major version.
-   */
-  async deleteContent(parameters: Parameters.DeleteContent, callback: Callback): Promise;
-  /**
-   * Moves a piece of content to the space's trash or purges it from the trash, depending on the content's type and
-   * status:
-   *
-   * - If the content's type is `page` or `blogpost` and its status is `current`, it will be trashed.
-   * - If the content's type is `page` or `blogpost` and its status is `trashed`, the content will be purged from the
-   *   trash and deleted permanently. Note, you must also set the `status` query parameter to `trashed` in your
-   *   request.
-   * - If the content's type is `comment` or `attachment`, it will be deleted permanently without being trashed.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'Delete' permission for the space that the
-   * content is in.
-   *
-   * @deprecated Will be removed in next major version.
-   */
-  async deleteContent(parameters: Parameters.DeleteContent, callback?: never): Promise;
-  async deleteContent(parameters: Parameters.DeleteContent, callback?: Callback): Promise {
-    const config: RequestConfig = {
-      url: `/api/content/${parameters.id}`,
-      method: 'DELETE',
-      params: {
-        status: parameters.status,
-      },
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-
-  /**
-   * Returns the most recent update for a piece of content.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to view the content.
-   *
-   * @deprecated Will be removed in next major version.
-   */
-  async getHistoryForContent(
-    parameters: Parameters.GetHistoryForContent,
-    callback: Callback,
-  ): Promise;
-  /**
-   * Returns the most recent update for a piece of content.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to view the content.
-   *
-   * @deprecated Will be removed in next major version.
-   */
-  async getHistoryForContent(
-    parameters: Parameters.GetHistoryForContent,
-    callback?: never,
-  ): Promise;
-  async getHistoryForContent(
-    parameters: Parameters.GetHistoryForContent,
-    callback?: Callback,
-  ): Promise {
-    const config: RequestConfig = {
-      url: `/api/content/${parameters.id}/history`,
-      method: 'GET',
-      params: {
-        expand: parameters.expand,
-      },
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-}
diff --git a/src/api/contentAttachments.ts b/src/api/contentAttachments.ts
deleted file mode 100644
index 2f9937d0..00000000
--- a/src/api/contentAttachments.ts
+++ /dev/null
@@ -1,286 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unnecessary-condition */
-import FormData from 'form-data';
-import type * as Models from './models';
-import type * as Parameters from './parameters';
-import type { Client } from '../clients';
-import type { Callback } from '../callback';
-import type { RequestConfig } from '../requestConfig';
-
-export class ContentAttachments {
-  constructor(private client: Client) {}
-
-  /**
-   * Returns the attachments for a piece of content.
-   *
-   * By default, the following objects are expanded: `metadata`.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to view the content. If the
-   * content is a blog post, 'View' permission for the space is required.
-   *
-   * @deprecated Will be removed in next major version.
-   */
-  async getAttachments>(
-    parameters: Parameters.GetAttachments,
-    callback: Callback,
-  ): Promise;
-  /**
-   * Returns the attachments for a piece of content.
-   *
-   * By default, the following objects are expanded: `metadata`.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to view the content. If the
-   * content is a blog post, 'View' permission for the space is required.
-   *
-   * @deprecated Will be removed in next major version.
-   */
-  async getAttachments>(
-    parameters: Parameters.GetAttachments,
-    callback?: never,
-  ): Promise;
-  async getAttachments>(
-    parameters: Parameters.GetAttachments,
-    callback?: Callback,
-  ): Promise {
-    const config: RequestConfig = {
-      url: `/api/content/${parameters.id}/child/attachment`,
-      method: 'GET',
-      params: {
-        start: parameters.start,
-        limit: parameters.limit,
-        filename: parameters.filename,
-        mediaType: parameters.mediaType,
-        expand: parameters.expand,
-      },
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-
-  /**
-   * Adds an attachment to a piece of content. This method only adds a new attachment. If you want to update an existing
-   * attachment, use [Create or update
-   * attachments](https://developer.atlassian.com/cloud/confluence/rest/api-group-content---attachments/#api-wiki-rest-api-content-id-child-attachment-put).
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to update the content.
-   */
-  async createAttachments>(
-    parameters: Parameters.CreateAttachments,
-    callback: Callback,
-  ): Promise;
-  /**
-   * Adds an attachment to a piece of content. This method only adds a new attachment. If you want to update an existing
-   * attachment, use [Create or update
-   * attachments](https://developer.atlassian.com/cloud/confluence/rest/api-group-content---attachments/#api-wiki-rest-api-content-id-child-attachment-put).
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to update the content.
-   */
-  async createAttachments>(
-    parameters: Parameters.CreateAttachments,
-    callback?: never,
-  ): Promise;
-  async createAttachments>(
-    parameters: Parameters.CreateAttachments,
-    callback?: Callback,
-  ): Promise {
-    const formData = new FormData();
-    const attachments = Array.isArray(parameters.attachments) ? parameters.attachments : [parameters.attachments];
-
-    attachments.forEach(attachment => {
-      formData.append('minorEdit', attachment.minorEdit.toString(), 'minorEdit');
-      formData.append('file', attachment.file, {
-        filename: attachment.filename,
-        contentType: attachment.contentType,
-      });
-
-      if (attachment.comment) {
-        formData.append('comment', attachment.comment, 'comment');
-      }
-    });
-
-    const config: RequestConfig = {
-      url: `/api/content/${parameters.id}/child/attachment`,
-      method: 'POST',
-      headers: {
-        'X-Atlassian-Token': 'no-check',
-        'Content-Type': 'multipart/form-data',
-        ...formData.getHeaders?.(),
-      },
-      params: {
-        status: parameters.status,
-      },
-      data: formData,
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-
-  /**
-   * Adds an attachment to a piece of content. If the attachment already exists for the content, then the attachment is
-   * updated (i.e. a new version of the attachment is created).
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to update the content.
-   */
-  async createOrUpdateAttachments>(
-    parameters: Parameters.CreateOrUpdateAttachments,
-    callback: Callback,
-  ): Promise;
-  /**
-   * Adds an attachment to a piece of content. If the attachment already exists for the content, then the attachment is
-   * updated (i.e. a new version of the attachment is created).
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to update the content.
-   */
-  async createOrUpdateAttachments>(
-    parameters: Parameters.CreateOrUpdateAttachments,
-    callback?: never,
-  ): Promise;
-  async createOrUpdateAttachments>(
-    parameters: Parameters.CreateOrUpdateAttachments,
-    callback?: Callback,
-  ): Promise {
-    const formData = new FormData();
-    const attachments = Array.isArray(parameters.attachments) ? parameters.attachments : [parameters.attachments];
-
-    attachments.forEach(attachment => {
-      formData.append('minorEdit', attachment.minorEdit.toString(), 'minorEdit');
-      formData.append('file', attachment.file, {
-        filename: attachment.filename,
-        contentType: attachment.contentType,
-      });
-
-      if (attachment.comment) {
-        formData.append('comment', attachment.comment, 'comment');
-      }
-    });
-
-    const config: RequestConfig = {
-      url: `/api/content/${parameters.id}/child/attachment`,
-      method: 'PUT',
-      headers: {
-        'X-Atlassian-Token': 'no-check',
-        'Content-Type': 'multipart/form-data',
-        ...formData.getHeaders?.(),
-      },
-      params: {
-        status: parameters.status,
-      },
-      data: formData,
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-
-  /**
-   * Updates the attachment properties, i.e. the non-binary data of an attachment like the filename, media-type,
-   * comment, and parent container.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to update the content.
-   */
-  async updateAttachmentProperties(
-    parameters: Parameters.UpdateAttachmentProperties,
-    callback: Callback,
-  ): Promise;
-  /**
-   * Updates the attachment properties, i.e. the non-binary data of an attachment like the filename, media-type,
-   * comment, and parent container.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to update the content.
-   */
-  async updateAttachmentProperties(
-    parameters: Parameters.UpdateAttachmentProperties,
-    callback?: never,
-  ): Promise;
-  async updateAttachmentProperties(
-    parameters: Parameters.UpdateAttachmentProperties,
-    callback?: Callback,
-  ): Promise {
-    const config: RequestConfig = {
-      url: `/api/content/${parameters.id}/child/attachment/${parameters.attachmentId}`,
-      method: 'PUT',
-      data: parameters.update,
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-
-  /**
-   * Updates the binary data of an attachment, given the attachment ID, and optionally the comment and the minor edit
-   * field.
-   *
-   * This method is essentially the same as [Create or update
-   * attachments](https://developer.atlassian.com/cloud/confluence/rest/api-group-content---attachments/#api-wiki-rest-api-content-id-child-attachment-put),
-   * except that it matches the attachment ID rather than the name.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to update the content.
-   */
-  async updateAttachmentData(
-    parameters: Parameters.UpdateAttachmentData,
-    callback: Callback,
-  ): Promise;
-  /**
-   * Updates the binary data of an attachment, given the attachment ID, and optionally the comment and the minor edit
-   * field.
-   *
-   * This method is essentially the same as [Create or update
-   * attachments](https://developer.atlassian.com/cloud/confluence/rest/api-group-content---attachments/#api-wiki-rest-api-content-id-child-attachment-put),
-   * except that it matches the attachment ID rather than the name.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to update the content.
-   */
-  async updateAttachmentData(
-    parameters: Parameters.UpdateAttachmentData,
-    callback?: never,
-  ): Promise;
-  async updateAttachmentData(
-    parameters: Parameters.UpdateAttachmentData,
-    callback?: Callback,
-  ): Promise {
-    const { attachment } = parameters;
-
-    const formData = new FormData();
-
-    formData.append('minorEdit', attachment.minorEdit.toString(), 'minorEdit');
-    formData.append('file', attachment.file, {
-      filename: attachment.filename,
-      contentType: attachment.contentType,
-    });
-
-    if (attachment.comment) {
-      formData.append('comment', attachment.comment, 'comment');
-    }
-
-    const config: RequestConfig = {
-      url: `/api/content/${parameters.id}/child/attachment/${parameters.attachmentId}/data`,
-      method: 'POST',
-      headers: {
-        'X-Atlassian-Token': 'no-check',
-        'Content-Type': 'multipart/form-data',
-        ...formData.getHeaders?.(),
-      },
-      data: formData,
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-
-  /** Redirects the client to a URL that serves an attachment's binary data. */
-  async downloadAttachment(parameters: Parameters.DownloadAttachment, callback: Callback): Promise;
-  /** Redirects the client to a URL that serves an attachment's binary data. */
-  async downloadAttachment(parameters: Parameters.DownloadAttachment, callback?: never): Promise;
-  async downloadAttachment(
-    parameters: Parameters.DownloadAttachment,
-    callback?: Callback,
-  ): Promise {
-    const config: RequestConfig = {
-      url: `/api/content/${parameters.id}/child/attachment/${parameters.attachmentId}/download`,
-      method: 'GET',
-      responseType: 'arraybuffer',
-      params: {
-        version: parameters.version,
-        status: parameters.status,
-      },
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-}
diff --git a/src/api/contentBody.ts b/src/api/contentBody.ts
deleted file mode 100644
index a76c40bc..00000000
--- a/src/api/contentBody.ts
+++ /dev/null
@@ -1,274 +0,0 @@
-import type * as Models from './models';
-import type * as Parameters from './parameters';
-import type { Client } from '../clients';
-import type { Callback } from '../callback';
-import type { RequestConfig } from '../requestConfig';
-
-export class ContentBody {
-  constructor(private client: Client) {}
-
-  /**
-   * Converts a content body from one format to another format.
-   *
-   * Supported conversions:
-   *
-   * - Storage: view, export_view, styled_view, editor
-   * - Editor: storage
-   * - View: none
-   * - Export_view: none
-   * - Styled_view: none
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: If request specifies 'contentIdContext',
-   * 'View' permission for the space, and permission to view the content.
-   *
-   * @deprecated Will be removed in next major version.
-   */
-  async convertContentBody(
-    parameters: Parameters.ConvertContentBody,
-    callback: Callback,
-  ): Promise;
-  /**
-   * Converts a content body from one format to another format.
-   *
-   * Supported conversions:
-   *
-   * - Storage: view, export_view, styled_view, editor
-   * - Editor: storage
-   * - View: none
-   * - Export_view: none
-   * - Styled_view: none
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: If request specifies 'contentIdContext',
-   * 'View' permission for the space, and permission to view the content.
-   *
-   * @deprecated Will be removed in next major version.
-   */
-  async convertContentBody(
-    parameters: Parameters.ConvertContentBody,
-    callback?: never,
-  ): Promise;
-  async convertContentBody(
-    parameters: Parameters.ConvertContentBody,
-    callback?: Callback,
-  ): Promise {
-    const config: RequestConfig = {
-      url: `/api/contentbody/convert/${parameters.to}`,
-      method: 'POST',
-      params: {
-        spaceKeyContext: parameters.spaceKeyContext,
-        contentIdContext: parameters.contentIdContext,
-        embeddedContentRender: parameters.embeddedContentRender,
-        expand: parameters.expand,
-      },
-      data: {
-        value: parameters.value,
-        representation: parameters.representation,
-        ...parameters.additionalProperties,
-      },
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-
-  /**
-   * Converts a content body from one format to another format asynchronously. Returns the asyncId for the asynchronous
-   * task.
-   *
-   * Supported conversions:
-   *
-   * - Atlas_doc_format: editor, export_view, storage, styled_view, view
-   * - Storage: atlas_doc_format, editor, export_view, styled_view, view
-   * - Editor: storage
-   *
-   * No other conversions are supported at the moment. Once a conversion is completed, it will be available for 5
-   * minutes at the result endpoint.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: If request specifies 'contentIdContext',
-   * 'View' permission for the space, and permission to view the content.
-   */
-  async asyncConvertContentBodyRequest(
-    parameters: Parameters.AsyncConvertContentBodyRequest,
-    callback: Callback,
-  ): Promise;
-  /**
-   * Converts a content body from one format to another format asynchronously. Returns the asyncId for the asynchronous
-   * task.
-   *
-   * Supported conversions:
-   *
-   * - Atlas_doc_format: editor, export_view, storage, styled_view, view
-   * - Storage: atlas_doc_format, editor, export_view, styled_view, view
-   * - Editor: storage
-   *
-   * No other conversions are supported at the moment. Once a conversion is completed, it will be available for 5
-   * minutes at the result endpoint.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: If request specifies 'contentIdContext',
-   * 'View' permission for the space, and permission to view the content.
-   */
-  async asyncConvertContentBodyRequest(
-    parameters: Parameters.AsyncConvertContentBodyRequest,
-    callback?: never,
-  ): Promise;
-  async asyncConvertContentBodyRequest(
-    parameters: Parameters.AsyncConvertContentBodyRequest,
-    callback?: Callback,
-  ): Promise {
-    const config: RequestConfig = {
-      url: `/api/contentbody/convert/async/${parameters.to}`,
-      method: 'POST',
-      params: {
-        spaceKeyContext: parameters.spaceKeyContext,
-        contentIdContext: parameters.contentIdContext,
-        allowCache: parameters.allowCache,
-        embeddedContentRender: parameters.embeddedContentRender,
-        expand: parameters.expand,
-      },
-      data: {
-        value: parameters.value,
-        representation: parameters.representation,
-        ...parameters.additionalProperties,
-      },
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-
-  /**
-   * Returns the asynchronous content body for the corresponding id if the task is complete or returns the status of the
-   * task.
-   *
-   * After the task is completed, the result can be obtained for 5 minutes, or until an identical conversion request is
-   * made again, with allowCache query param set to false.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: If request specifies 'contentIdContext',
-   * 'View' permission for the space, and permission to view the content.
-   */
-  async asyncConvertContentBodyResponse(
-    parameters: Parameters.AsyncConvertContentBodyResponse,
-    callback: Callback,
-  ): Promise;
-  /**
-   * Returns the asynchronous content body for the corresponding id if the task is complete or returns the status of the
-   * task.
-   *
-   * After the task is completed, the result can be obtained for 5 minutes, or until an identical conversion request is
-   * made again, with allowCache query param set to false.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: If request specifies 'contentIdContext',
-   * 'View' permission for the space, and permission to view the content.
-   */
-  async asyncConvertContentBodyResponse(
-    parameters: Parameters.AsyncConvertContentBodyResponse,
-    callback?: never,
-  ): Promise;
-  async asyncConvertContentBodyResponse(
-    parameters: Parameters.AsyncConvertContentBodyResponse,
-    callback?: Callback,
-  ): Promise {
-    const config: RequestConfig = {
-      url: `/api/contentbody/convert/async/${parameters.id}`,
-      method: 'GET',
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-
-  /**
-   * Returns the content body for the corresponding `asyncId` of a completed conversion task. If the task is not
-   * completed, the task status is returned instead.
-   *
-   * Once a conversion task is completed, the result can be obtained for up to 5 minutes, or until an identical
-   * conversion request is made again with the `allowCache` parameter set to false.
-   *
-   * Note that there is a maximum limit of 50 task results per request to this endpoint.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to access the Confluence site
-   * ('Can use' global permission).
-   */
-  async bulkAsyncConvertContentBodyResponse(
-    parameters: Parameters.BulkAsyncConvertContentBodyResponse,
-    callback: Callback,
-  ): Promise;
-  /**
-   * Returns the content body for the corresponding `asyncId` of a completed conversion task. If the task is not
-   * completed, the task status is returned instead.
-   *
-   * Once a conversion task is completed, the result can be obtained for up to 5 minutes, or until an identical
-   * conversion request is made again with the `allowCache` parameter set to false.
-   *
-   * Note that there is a maximum limit of 50 task results per request to this endpoint.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to access the Confluence site
-   * ('Can use' global permission).
-   */
-  async bulkAsyncConvertContentBodyResponse(
-    parameters: Parameters.BulkAsyncConvertContentBodyResponse,
-    callback?: never,
-  ): Promise;
-  async bulkAsyncConvertContentBodyResponse(
-    parameters: Parameters.BulkAsyncConvertContentBodyResponse,
-    callback?: Callback,
-  ): Promise {
-    const config: RequestConfig = {
-      url: '/api/contentbody/convert/async/bulk/tasks',
-      method: 'GET',
-      params: {
-        ids: parameters.ids,
-      },
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-
-  /**
-   * Asynchronously converts content bodies from one format to another format in bulk. Use the Content body REST API to
-   * get the status of conversion tasks. Note that there is a maximum limit of 10 conversions per request to this
-   * endpoint.
-   *
-   * Supported conversions:
-   *
-   * - Storage: editor, export_view, styled_view, view
-   * - Editor: storage
-   *
-   * Once a conversion task is completed, it is available for polling for up to 5 minutes.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'View' permission for the space, and
-   * permission to view the content if the `spaceKeyContext` or `contentIdContext` are present.
-   */
-  async bulkAsyncConvertContentBodyRequest(
-    parameters: Parameters.BulkAsyncConvertContentBodyRequest,
-    callback: Callback,
-  ): Promise;
-  /**
-   * Asynchronously converts content bodies from one format to another format in bulk. Use the Content body REST API to
-   * get the status of conversion tasks. Note that there is a maximum limit of 10 conversions per request to this
-   * endpoint.
-   *
-   * Supported conversions:
-   *
-   * - Storage: editor, export_view, styled_view, view
-   * - Editor: storage
-   *
-   * Once a conversion task is completed, it is available for polling for up to 5 minutes.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'View' permission for the space, and
-   * permission to view the content if the `spaceKeyContext` or `contentIdContext` are present.
-   */
-  async bulkAsyncConvertContentBodyRequest(
-    parameters: Parameters.BulkAsyncConvertContentBodyRequest,
-    callback?: never,
-  ): Promise;
-  async bulkAsyncConvertContentBodyRequest(
-    parameters: Parameters.BulkAsyncConvertContentBodyRequest,
-    callback?: Callback,
-  ): Promise {
-    const config: RequestConfig = {
-      url: '/api/contentbody/convert/async/bulk/tasks',
-      method: 'POST',
-      data: parameters,
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-}
diff --git a/src/api/contentChildrenAndDescendants.ts b/src/api/contentChildrenAndDescendants.ts
deleted file mode 100644
index a5985464..00000000
--- a/src/api/contentChildrenAndDescendants.ts
+++ /dev/null
@@ -1,401 +0,0 @@
-import type * as Models from './models';
-import type * as Parameters from './parameters';
-import type { Client } from '../clients';
-import type { Callback } from '../callback';
-import type { RequestConfig } from '../requestConfig';
-
-export class ContentChildrenAndDescendants {
-  constructor(private client: Client) {}
-
-  /**
-   * Returns a map of the direct children of a piece of content. A piece of content has different types of child
-   * content, depending on its type. These are the default parent-child content type relationships:
-   *
-   * - `page`: child content is `page`, `comment`, `attachment`
-   * - `blogpost`: child content is `comment`, `attachment`
-   * - `attachment`: child content is `comment`
-   * - `comment`: child content is `attachment`
-   *
-   * Apps can override these default relationships. Apps can also introduce new content types that create new
-   * parent-child content relationships.
-   *
-   * Note, the map will always include all child content types that are valid for the content. However, if the content
-   * has no instances of a child content type, the map will contain an empty array for that child content type.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'View' permission for the space, and
-   * permission to view the content if it is a page.
-   *
-   * @deprecated Will be removed in next major version.
-   */
-  async getContentChildren(
-    parameters: Parameters.GetContentChildren,
-    callback: Callback,
-  ): Promise;
-  /**
-   * Returns a map of the direct children of a piece of content. A piece of content has different types of child
-   * content, depending on its type. These are the default parent-child content type relationships:
-   *
-   * - `page`: child content is `page`, `comment`, `attachment`
-   * - `blogpost`: child content is `comment`, `attachment`
-   * - `attachment`: child content is `comment`
-   * - `comment`: child content is `attachment`
-   *
-   * Apps can override these default relationships. Apps can also introduce new content types that create new
-   * parent-child content relationships.
-   *
-   * Note, the map will always include all child content types that are valid for the content. However, if the content
-   * has no instances of a child content type, the map will contain an empty array for that child content type.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'View' permission for the space, and
-   * permission to view the content if it is a page.
-   *
-   * @deprecated Will be removed in next major version.
-   */
-  async getContentChildren(
-    parameters: Parameters.GetContentChildren,
-    callback?: never,
-  ): Promise;
-  async getContentChildren(
-    parameters: Parameters.GetContentChildren,
-    callback?: Callback,
-  ): Promise {
-    const config: RequestConfig = {
-      url: `/api/content/${parameters.id}/child`,
-      method: 'GET',
-      params: {
-        expand: parameters.expand,
-        parentVersion: parameters.parentVersion,
-        start: parameters.start,
-        limit: parameters.limit,
-      },
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-
-  /**
-   * Move a page to a new location relative to a target page:
-   *
-   * - `before` - move the page under the same parent as the target, before the target in the list of children
-   * - `after` - move the page under the same parent as the target, after the target in the list of children
-   * - `append` - move the page to be a child of the target
-   *
-   * Caution: This API can move pages to the top level of a space. Top-level pages are difficult to find in the UI
-   * because they do not show up in the page tree display. To avoid this, never use `before` or `after` positions when
-   * the `targetId` is a top-level page.
-   */
-  async movePage(parameters: Parameters.MovePage, callback: Callback): Promise;
-  /**
-   * Move a page to a new location relative to a target page:
-   *
-   * - `before` - move the page under the same parent as the target, before the target in the list of children
-   * - `after` - move the page under the same parent as the target, after the target in the list of children
-   * - `append` - move the page to be a child of the target
-   *
-   * Caution: This API can move pages to the top level of a space. Top-level pages are difficult to find in the UI
-   * because they do not show up in the page tree display. To avoid this, never use `before` or `after` positions when
-   * the `targetId` is a top-level page.
-   */
-  async movePage(parameters: Parameters.MovePage, callback?: never): Promise;
-  async movePage(parameters: Parameters.MovePage, callback?: Callback): Promise {
-    const config: RequestConfig = {
-      url: `/api/content/${parameters.pageId}/move/${parameters.position}/${parameters.targetId}`,
-      method: 'PUT',
-      headers: {
-        'Content-Type': 'application/json',
-      },
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-
-  /**
-   * Returns all children of a given type, for a piece of content. A piece of content has different types of child
-   * content, depending on its type:
-   *
-   * - `page`: child content is `page`, `comment`, `attachment`
-   * - `blogpost`: child content is `comment`, `attachment`
-   * - `attachment`: child content is `comment`
-   * - `comment`: child content is `attachment`
-   *
-   * Custom content types that are provided by apps can also be returned.
-   *
-   * Note, this method only returns direct children. To return children at all levels, use [Get descendants by
-   * type](#api-content-id-descendant-type-get).
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'View' permission for the space, and
-   * permission to view the content if it is a page.
-   *
-   * @deprecated Will be removed in next major version.
-   */
-  async getContentChildrenByType(
-    parameters: Parameters.GetContentChildrenByType,
-    callback: Callback,
-  ): Promise;
-  /**
-   * Returns all children of a given type, for a piece of content. A piece of content has different types of child
-   * content, depending on its type:
-   *
-   * - `page`: child content is `page`, `comment`, `attachment`
-   * - `blogpost`: child content is `comment`, `attachment`
-   * - `attachment`: child content is `comment`
-   * - `comment`: child content is `attachment`
-   *
-   * Custom content types that are provided by apps can also be returned.
-   *
-   * Note, this method only returns direct children. To return children at all levels, use [Get descendants by
-   * type](#api-content-id-descendant-type-get).
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'View' permission for the space, and
-   * permission to view the content if it is a page.
-   *
-   * @deprecated Will be removed in next major version.
-   */
-  async getContentChildrenByType(
-    parameters: Parameters.GetContentChildrenByType,
-    callback?: never,
-  ): Promise;
-  async getContentChildrenByType(
-    parameters: Parameters.GetContentChildrenByType,
-    callback?: Callback,
-  ): Promise {
-    const config: RequestConfig = {
-      url: `/api/content/${parameters.id}/child/${parameters.type}`,
-      method: 'GET',
-      params: {
-        parentVersion: parameters.parentVersion,
-        start: parameters.start,
-        limit: parameters.limit,
-      },
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-
-  /**
-   * Returns a map of the descendants of a piece of content. This is similar to [Get content
-   * children](#api-content-id-child-get), except that this method returns child pages at all levels, rather than just
-   * the direct child pages.
-   *
-   * A piece of content has different types of descendants, depending on its type:
-   *
-   * - `page`: descendant is `page`, `whiteboard`, `database`, `embed`, `folder`, `comment`, `attachment`
-   * - `whiteboard`: descendant is `page`, `whiteboard`, `database`, `embed`, `folder`, `comment`, `attachment`
-   * - `database`: descendant is `page`, `whiteboard`, `database`, `embed`, `folder`, `comment`, `attachment`
-   * - `embed`: descendant is `page`, `whiteboard`, `database`, `embed`, `folder`, `comment`, `attachment`
-   * - `folder`: descendant is `page`, `whiteboard`, `database`, `embed`, `folder`, `comment`, `attachment`
-   * - `blogpost`: descendant is `comment`, `attachment`
-   * - `attachment`: descendant is `comment`
-   * - `comment`: descendant is `attachment`
-   *
-   * The map will always include all descendant types that are valid for the content. However, if the content has no
-   * instances of a descendant type, the map will contain an empty array for that descendant type.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'View' permission for the space, and
-   * permission to view the content if it is a page.
-   */
-  async getContentDescendants(
-    parameters: Parameters.GetContentDescendants,
-    callback: Callback,
-  ): Promise;
-  /**
-   * Returns a map of the descendants of a piece of content. This is similar to [Get content
-   * children](#api-content-id-child-get), except that this method returns child pages at all levels, rather than just
-   * the direct child pages.
-   *
-   * A piece of content has different types of descendants, depending on its type:
-   *
-   * - `page`: descendant is `page`, `whiteboard`, `database`, `embed`, `folder`, `comment`, `attachment`
-   * - `whiteboard`: descendant is `page`, `whiteboard`, `database`, `embed`, `folder`, `comment`, `attachment`
-   * - `database`: descendant is `page`, `whiteboard`, `database`, `embed`, `folder`, `comment`, `attachment`
-   * - `embed`: descendant is `page`, `whiteboard`, `database`, `embed`, `folder`, `comment`, `attachment`
-   * - `folder`: descendant is `page`, `whiteboard`, `database`, `embed`, `folder`, `comment`, `attachment`
-   * - `blogpost`: descendant is `comment`, `attachment`
-   * - `attachment`: descendant is `comment`
-   * - `comment`: descendant is `attachment`
-   *
-   * The map will always include all descendant types that are valid for the content. However, if the content has no
-   * instances of a descendant type, the map will contain an empty array for that descendant type.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'View' permission for the space, and
-   * permission to view the content if it is a page.
-   */
-  async getContentDescendants(
-    parameters: Parameters.GetContentDescendants,
-    callback?: never,
-  ): Promise;
-  async getContentDescendants(
-    parameters: Parameters.GetContentDescendants,
-    callback?: Callback,
-  ): Promise {
-    const config: RequestConfig = {
-      url: `/api/content/${parameters.id}/descendant`,
-      method: 'GET',
-      params: {
-        expand: parameters.expand,
-      },
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-
-  /**
-   * Returns all descendants of a given type, for a piece of content. This is similar to [Get content children by
-   * type](#api-content-id-child-type-get), except that this method returns child pages at all levels, rather than just
-   * the direct child pages.
-   *
-   * A piece of content has different types of descendants, depending on its type:
-   *
-   * - `page`: descendant is `page`, `whiteboard`, `database`, `embed`, `folder`, `comment`, `attachment`
-   * - `whiteboard`: descendant is `page`, `whiteboard`, `database`, `embed`, `folder`, `comment`, `attachment`
-   * - `database`: descendant is `page`, `whiteboard`, `database`, `embed`, `folder`, `comment`, `attachment`
-   * - `embed`: descendant is `page`, `whiteboard`, `database`, `embed`, `folder`, `comment`, `attachment`
-   * - `folder`: descendant is `page`, `whiteboard`, `database`, `embed`, `folder`, `comment`, `attachment`
-   * - `blogpost`: descendant is `comment`, `attachment`
-   * - `attachment`: descendant is `comment`
-   * - `comment`: descendant is `attachment`
-   *
-   * Custom content types that are provided by apps can also be returned.
-   *
-   * If the expand query parameter is used with the `body.export_view` and/or `body.styled_view` properties, then the
-   * query limit parameter will be restricted to a maximum value of 25.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'View' permission for the space, and
-   * permission to view the content if it is a page.
-   */
-  async getDescendantsOfType(
-    parameters: Parameters.GetDescendantsOfType,
-    callback: Callback,
-  ): Promise;
-  /**
-   * Returns all descendants of a given type, for a piece of content. This is similar to [Get content children by
-   * type](#api-content-id-child-type-get), except that this method returns child pages at all levels, rather than just
-   * the direct child pages.
-   *
-   * A piece of content has different types of descendants, depending on its type:
-   *
-   * - `page`: descendant is `page`, `whiteboard`, `database`, `embed`, `folder`, `comment`, `attachment`
-   * - `whiteboard`: descendant is `page`, `whiteboard`, `database`, `embed`, `folder`, `comment`, `attachment`
-   * - `database`: descendant is `page`, `whiteboard`, `database`, `embed`, `folder`, `comment`, `attachment`
-   * - `embed`: descendant is `page`, `whiteboard`, `database`, `embed`, `folder`, `comment`, `attachment`
-   * - `folder`: descendant is `page`, `whiteboard`, `database`, `embed`, `folder`, `comment`, `attachment`
-   * - `blogpost`: descendant is `comment`, `attachment`
-   * - `attachment`: descendant is `comment`
-   * - `comment`: descendant is `attachment`
-   *
-   * Custom content types that are provided by apps can also be returned.
-   *
-   * If the expand query parameter is used with the `body.export_view` and/or `body.styled_view` properties, then the
-   * query limit parameter will be restricted to a maximum value of 25.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'View' permission for the space, and
-   * permission to view the content if it is a page.
-   */
-  async getDescendantsOfType(
-    parameters: Parameters.GetDescendantsOfType,
-    callback?: never,
-  ): Promise;
-  async getDescendantsOfType(
-    parameters: Parameters.GetDescendantsOfType,
-    callback?: Callback,
-  ): Promise {
-    const config: RequestConfig = {
-      url: `/api/content/${parameters.id}/descendant/${parameters.type}`,
-      method: 'GET',
-      params: {
-        depth: parameters.depth,
-        start: parameters.start,
-        limit: parameters.limit,
-        expand: parameters.expand,
-      },
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-
-  /**
-   * Copy page hierarchy allows the copying of an entire hierarchy of pages and their associated properties, permissions
-   * and attachments. The id path parameter refers to the content id of the page to copy, and the new parent of this
-   * copied page is defined using the destinationPageId in the request body. The titleOptions object defines the rules
-   * of renaming page titles during the copy; for example, search and replace can be used in conjunction to rewrite the
-   * copied page titles.
-   */
-  async copyPageHierarchy(
-    parameters: Parameters.CopyPageHierarchy,
-    callback: Callback,
-  ): Promise;
-  /**
-   * Copy page hierarchy allows the copying of an entire hierarchy of pages and their associated properties, permissions
-   * and attachments. The id path parameter refers to the content id of the page to copy, and the new parent of this
-   * copied page is defined using the destinationPageId in the request body. The titleOptions object defines the rules
-   * of renaming page titles during the copy; for example, search and replace can be used in conjunction to rewrite the
-   * copied page titles.
-   */
-  async copyPageHierarchy(parameters: Parameters.CopyPageHierarchy, callback?: never): Promise;
-  async copyPageHierarchy(
-    parameters: Parameters.CopyPageHierarchy,
-    callback?: Callback,
-  ): Promise {
-    const config: RequestConfig = {
-      url: `/api/content/${parameters.id}/pagehierarchy/copy`,
-      method: 'POST',
-      data: {
-        copyAttachments: parameters.copyAttachments,
-        copyPermissions: parameters.copyPermissions,
-        copyProperties: parameters.copyProperties,
-        copyLabels: parameters.copyLabels,
-        copyCustomContents: parameters.copyCustomContents,
-        copyDescendants: parameters.copyDescendants,
-        destinationPageId: parameters.destinationPageId,
-        titleOptions: parameters.titleOptions,
-      },
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-
-  /**
-   * Copies a single page and its associated properties, permissions, attachments, and custom contents. The `id` path
-   * parameter refers to the content ID of the page to copy. The target of the page to be copied is defined using the
-   * `destination` in the request body and can be one of the following types.
-   *
-   * - `space`: page will be copied to the specified space as a root page on the space
-   * - `parent_page`: page will be copied as a child of the specified parent page
-   * - `parent_content`: page will be copied as a child of the specified parent content
-   * - `existing_page`: page will be copied and replace the specified page
-   *
-   * By default, the following objects are expanded: `space`, `history`, `version`.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'Add' permission for the space that the
-   * content will be copied in and permission to update the content if copying to an `existing_page`.
-   */
-  async copyPage(parameters: Parameters.CopyPage, callback: Callback): Promise;
-  /**
-   * Copies a single page and its associated properties, permissions, attachments, and custom contents. The `id` path
-   * parameter refers to the content ID of the page to copy. The target of the page to be copied is defined using the
-   * `destination` in the request body and can be one of the following types.
-   *
-   * - `space`: page will be copied to the specified space as a root page on the space
-   * - `parent_page`: page will be copied as a child of the specified parent page
-   * - `parent_content`: page will be copied as a child of the specified parent content
-   * - `existing_page`: page will be copied and replace the specified page
-   *
-   * By default, the following objects are expanded: `space`, `history`, `version`.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'Add' permission for the space that the
-   * content will be copied in and permission to update the content if copying to an `existing_page`.
-   */
-  async copyPage(parameters: Parameters.CopyPage, callback?: never): Promise;
-  async copyPage(parameters: Parameters.CopyPage, callback?: Callback): Promise {
-    const config: RequestConfig = {
-      url: `/api/content/${parameters.id}/copy`,
-      method: 'POST',
-      params: {
-        expand: parameters.expand,
-      },
-      data: parameters.bodyParameters,
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-}
diff --git a/src/api/contentComments.ts b/src/api/contentComments.ts
deleted file mode 100644
index 5fd67382..00000000
--- a/src/api/contentComments.ts
+++ /dev/null
@@ -1,54 +0,0 @@
-import type * as Models from './models';
-import type * as Parameters from './parameters';
-import type { Callback } from '../callback';
-import type { Client } from '../clients';
-import type { RequestConfig } from '../requestConfig';
-
-/** @deprecated Will be removed in next major version. */
-export class ContentComments {
-  constructor(private client: Client) {}
-
-  /**
-   * Returns the comments on a piece of content.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'View' permission for the space, and
-   * permission to view the content if it is a page.
-   *
-   * @deprecated Will be removed in next major version.
-   */
-  async getContentComments(
-    parameters: Parameters.GetContentComments,
-    callback: Callback,
-  ): Promise;
-  /**
-   * Returns the comments on a piece of content.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'View' permission for the space, and
-   * permission to view the content if it is a page.
-   *
-   * @deprecated Will be removed in next major version.
-   */
-  async getContentComments(
-    parameters: Parameters.GetContentComments,
-    callback?: never,
-  ): Promise;
-  async getContentComments(
-    parameters: Parameters.GetContentComments,
-    callback?: Callback,
-  ): Promise {
-    const config: RequestConfig = {
-      url: `/api/content/${parameters.id}/child/comment`,
-      method: 'GET',
-      params: {
-        parentVersion: parameters.parentVersion,
-        start: parameters.start,
-        limit: parameters.limit,
-        location: parameters.location,
-        depth: parameters.depth,
-        expand: parameters.expand,
-      },
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-}
diff --git a/src/api/contentLabels.ts b/src/api/contentLabels.ts
deleted file mode 100644
index 60a90a44..00000000
--- a/src/api/contentLabels.ts
+++ /dev/null
@@ -1,178 +0,0 @@
-import type * as Models from './models';
-import type * as Parameters from './parameters';
-import type { Client } from '../clients';
-import type { Callback } from '../callback';
-import type { RequestConfig } from '../requestConfig';
-
-export class ContentLabels {
-  constructor(private client: Client) {}
-
-  /**
-   * Returns the labels on a piece of content.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'View' permission for the space and
-   * permission to view the content if it is a page.
-   *
-   * @deprecated Will be removed in next major version.
-   */
-  async getLabelsForContent(
-    parameters: Parameters.GetLabelsForContent,
-    callback: Callback,
-  ): Promise;
-  /**
-   * Returns the labels on a piece of content.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'View' permission for the space and
-   * permission to view the content if it is a page.
-   *
-   * @deprecated Will be removed in next major version.
-   */
-  async getLabelsForContent(
-    parameters: Parameters.GetLabelsForContent,
-    callback?: never,
-  ): Promise;
-  async getLabelsForContent(
-    parameters: Parameters.GetLabelsForContent,
-    callback?: Callback,
-  ): Promise {
-    const config: RequestConfig = {
-      url: `/api/content/${parameters.id}/label`,
-      method: 'GET',
-      params: {
-        prefix: parameters.prefix,
-        start: parameters.start,
-        limit: parameters.limit,
-      },
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-
-  /**
-   * Adds labels to a piece of content. Does not modify the existing labels.
-   *
-   * Notes:
-   *
-   * - Labels can also be added when creating content ([Create content](#api-content-post)).
-   * - Labels can be updated when updating content ([Update content](#api-content-id-put)). This will delete the existing
-   *   labels and replace them with the labels in the request.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to update the content.
-   */
-  async addLabelsToContent(
-    parameters: Parameters.AddLabelsToContent,
-    callback: Callback,
-  ): Promise;
-  /**
-   * Adds labels to a piece of content. Does not modify the existing labels.
-   *
-   * Notes:
-   *
-   * - Labels can also be added when creating content ([Create content](#api-content-post)).
-   * - Labels can be updated when updating content ([Update content](#api-content-id-put)). This will delete the existing
-   *   labels and replace them with the labels in the request.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to update the content.
-   */
-  async addLabelsToContent(
-    parameters: Parameters.AddLabelsToContent,
-    callback?: never,
-  ): Promise;
-  async addLabelsToContent(
-    parameters: Parameters.AddLabelsToContent,
-    callback?: Callback,
-  ): Promise {
-    const config: RequestConfig = {
-      url: `/api/content/${parameters.id}/label`,
-      method: 'POST',
-      params: {
-        'use-400-error-response': parameters['use-400-error-response'],
-      },
-      data: parameters.body,
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-
-  /**
-   * Removes a label from a piece of content. Labels can't be deleted from archived content. This is similar to [Remove
-   * label from content](#api-content-id-label-label-delete) except that the label name is specified via a query
-   * parameter.
-   *
-   * Use this method if the label name has "/" characters, as [Remove label from content using query
-   * parameter](#api-content-id-label-delete) does not accept "/" characters for the label name.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to update the content.
-   */
-  async removeLabelFromContentUsingQueryParameter(
-    parameters: Parameters.RemoveLabelFromContentUsingQueryParameter,
-    callback: Callback,
-  ): Promise;
-  /**
-   * Removes a label from a piece of content. Labels can't be deleted from archived content. This is similar to [Remove
-   * label from content](#api-content-id-label-label-delete) except that the label name is specified via a query
-   * parameter.
-   *
-   * Use this method if the label name has "/" characters, as [Remove label from content using query
-   * parameter](#api-content-id-label-delete) does not accept "/" characters for the label name.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to update the content.
-   */
-  async removeLabelFromContentUsingQueryParameter(
-    parameters: Parameters.RemoveLabelFromContentUsingQueryParameter,
-    callback?: never,
-  ): Promise;
-  async removeLabelFromContentUsingQueryParameter(
-    parameters: Parameters.RemoveLabelFromContentUsingQueryParameter,
-    callback?: Callback,
-  ): Promise {
-    const config: RequestConfig = {
-      url: `/api/content/${parameters.id}/label`,
-      method: 'DELETE',
-      params: {
-        name: parameters.name,
-      },
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-
-  /**
-   * Removes a label from a piece of content. Labels can't be deleted from archived content. This is similar to [Remove
-   * label from content using query parameter](#api-content-id-label-delete) except that the label name is specified via
-   * a path parameter.
-   *
-   * Use this method if the label name does not have "/" characters, as the path parameter does not accept "/"
-   * characters for security reasons. Otherwise, use [Remove label from content using query
-   * parameter](#api-content-id-label-delete).
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to update the content.
-   */
-  async removeLabelFromContent(
-    parameters: Parameters.RemoveLabelFromContent,
-    callback: Callback,
-  ): Promise;
-  /**
-   * Removes a label from a piece of content. Labels can't be deleted from archived content. This is similar to [Remove
-   * label from content using query parameter](#api-content-id-label-delete) except that the label name is specified via
-   * a path parameter.
-   *
-   * Use this method if the label name does not have "/" characters, as the path parameter does not accept "/"
-   * characters for security reasons. Otherwise, use [Remove label from content using query
-   * parameter](#api-content-id-label-delete).
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to update the content.
-   */
-  async removeLabelFromContent(parameters: Parameters.RemoveLabelFromContent, callback?: never): Promise;
-  async removeLabelFromContent(
-    parameters: Parameters.RemoveLabelFromContent,
-    callback?: Callback,
-  ): Promise {
-    const config: RequestConfig = {
-      url: `/api/content/${parameters.id}/label/${parameters.label}`,
-      method: 'DELETE',
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-}
diff --git a/src/api/contentMacroBody.ts b/src/api/contentMacroBody.ts
deleted file mode 100644
index a6b969a0..00000000
--- a/src/api/contentMacroBody.ts
+++ /dev/null
@@ -1,254 +0,0 @@
-import type * as Models from './models';
-import type * as Parameters from './parameters';
-import type { Client } from '../clients';
-import type { Callback } from '../callback';
-import type { RequestConfig } from '../requestConfig';
-
-export class ContentMacroBody {
-  constructor(private client: Client) {}
-
-  /**
-   * Returns the body of a macro in storage format, for the given macro ID. This includes information like the name of
-   * the macro, the body of the macro, and any macro parameters. This method is mainly used by Cloud apps.
-   *
-   * About the macro ID: When a macro is created in a new version of content, Confluence will generate a random ID for
-   * it, unless an ID is specified (by an app). The macro ID will look similar to this:
-   * '50884bd9-0cb8-41d5-98be-f80943c14f96'. The ID is then persisted as new versions of content are created, and is
-   * only modified by Confluence if there are conflicting IDs.
-   *
-   * For Forge macros, the value for macro ID is the "local ID" of that particular ADF node. This value can be retrieved
-   * either client-side by calling view.getContext() and accessing "localId" on the resulting object, or server-side by
-   * examining the "local-id" parameter node inside the "parameters" node.
-   *
-   * Note that there are other attributes named "local-id", but only this particular one is used to store the macro ID.
-   *
-   * Example:  com.atlassian.ecosystem 
-   * e9c4aa10-73fa-417c-888d-48c719ae4165 
-   * 
-   *
-   * Note, to preserve backwards compatibility this resource will also match on the hash of the macro body, even if a
-   * macro ID is found. This check will eventually become redundant, as macro IDs are generated for pages and
-   * transparently propagate out to all instances.
-   *
-   * This backwards compatibility logic does not apply to Forge macros; those can only be retrieved by their ID.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to view the content that the
-   * macro is in.
-   */
-  async getMacroBodyByMacroId(
-    parameters: Parameters.GetMacroBodyByMacroId,
-    callback: Callback,
-  ): Promise;
-  /**
-   * Returns the body of a macro in storage format, for the given macro ID. This includes information like the name of
-   * the macro, the body of the macro, and any macro parameters. This method is mainly used by Cloud apps.
-   *
-   * About the macro ID: When a macro is created in a new version of content, Confluence will generate a random ID for
-   * it, unless an ID is specified (by an app). The macro ID will look similar to this:
-   * '50884bd9-0cb8-41d5-98be-f80943c14f96'. The ID is then persisted as new versions of content are created, and is
-   * only modified by Confluence if there are conflicting IDs.
-   *
-   * For Forge macros, the value for macro ID is the "local ID" of that particular ADF node. This value can be retrieved
-   * either client-side by calling view.getContext() and accessing "localId" on the resulting object, or server-side by
-   * examining the "local-id" parameter node inside the "parameters" node.
-   *
-   * Note that there are other attributes named "local-id", but only this particular one is used to store the macro ID.
-   *
-   * Example:  com.atlassian.ecosystem 
-   * e9c4aa10-73fa-417c-888d-48c719ae4165 
-   * 
-   *
-   * Note, to preserve backwards compatibility this resource will also match on the hash of the macro body, even if a
-   * macro ID is found. This check will eventually become redundant, as macro IDs are generated for pages and
-   * transparently propagate out to all instances.
-   *
-   * This backwards compatibility logic does not apply to Forge macros; those can only be retrieved by their ID.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to view the content that the
-   * macro is in.
-   */
-  async getMacroBodyByMacroId(
-    parameters: Parameters.GetMacroBodyByMacroId,
-    callback?: never,
-  ): Promise;
-  async getMacroBodyByMacroId(
-    parameters: Parameters.GetMacroBodyByMacroId,
-    callback?: Callback,
-  ): Promise {
-    const config: RequestConfig = {
-      url: `/api/content/${parameters.id}/history/${parameters.version}/macro/id/${parameters.macroId}`,
-      method: 'GET',
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-
-  /**
-   * Returns the body of a macro in format specified in path, for the given macro ID. This includes information like the
-   * name of the macro, the body of the macro, and any macro parameters.
-   *
-   * About the macro ID: When a macro is created in a new version of content, Confluence will generate a random ID for
-   * it, unless an ID is specified (by an app). The macro ID will look similar to this:
-   * '50884bd9-0cb8-41d5-98be-f80943c14f96'. The ID is then persisted as new versions of content are created, and is
-   * only modified by Confluence if there are conflicting IDs.
-   *
-   * For Forge macros, the value for macro ID is the "local ID" of that particular ADF node. This value can be retrieved
-   * either client-side by calling view.getContext() and accessing "localId" on the resulting object, or server-side by
-   * examining the "local-id" parameter node inside the "parameters" node.
-   *
-   * Note that there are other attributes named "local-id", but only this particular one is used to store the macro ID.
-   *
-   * Example:  com.atlassian.ecosystem 
-   * e9c4aa10-73fa-417c-888d-48c719ae4165 
-   * 
-   *
-   * Note, to preserve backwards compatibility this resource will also match on the hash of the macro body, even if a
-   * macro ID is found. This check will eventually become redundant, as macro IDs are generated for pages and
-   * transparently propagate out to all instances.
-   *
-   * This backwards compatibility logic does not apply to Forge macros; those can only be retrieved by their ID.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to view the content that the
-   * macro is in.
-   */
-  async getAndConvertMacroBodyByMacroId(
-    parameters: Parameters.GetAndConvertMacroBodyByMacroId,
-    callback: Callback,
-  ): Promise;
-  /**
-   * Returns the body of a macro in format specified in path, for the given macro ID. This includes information like the
-   * name of the macro, the body of the macro, and any macro parameters.
-   *
-   * About the macro ID: When a macro is created in a new version of content, Confluence will generate a random ID for
-   * it, unless an ID is specified (by an app). The macro ID will look similar to this:
-   * '50884bd9-0cb8-41d5-98be-f80943c14f96'. The ID is then persisted as new versions of content are created, and is
-   * only modified by Confluence if there are conflicting IDs.
-   *
-   * For Forge macros, the value for macro ID is the "local ID" of that particular ADF node. This value can be retrieved
-   * either client-side by calling view.getContext() and accessing "localId" on the resulting object, or server-side by
-   * examining the "local-id" parameter node inside the "parameters" node.
-   *
-   * Note that there are other attributes named "local-id", but only this particular one is used to store the macro ID.
-   *
-   * Example:  com.atlassian.ecosystem 
-   * e9c4aa10-73fa-417c-888d-48c719ae4165 
-   * 
-   *
-   * Note, to preserve backwards compatibility this resource will also match on the hash of the macro body, even if a
-   * macro ID is found. This check will eventually become redundant, as macro IDs are generated for pages and
-   * transparently propagate out to all instances.
-   *
-   * This backwards compatibility logic does not apply to Forge macros; those can only be retrieved by their ID.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to view the content that the
-   * macro is in.
-   */
-  async getAndConvertMacroBodyByMacroId(
-    parameters: Parameters.GetAndConvertMacroBodyByMacroId,
-    callback?: never,
-  ): Promise;
-  async getAndConvertMacroBodyByMacroId(
-    parameters: Parameters.GetAndConvertMacroBodyByMacroId,
-    callback?: Callback,
-  ): Promise {
-    const config: RequestConfig = {
-      url: `/api/content/${parameters.id}/history/${parameters.version}/macro/id/${parameters.macroId}/convert/${parameters.to}`,
-      method: 'GET',
-      params: {
-        spaceKeyContext: parameters.spaceKeyContext,
-        embeddedContentRender: parameters.embeddedContentRender,
-        expand: parameters.expand,
-      },
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-
-  /**
-   * Returns Async Id of the conversion task which will convert the macro into a content body of the desired format. The
-   * result will be available for 5 minutes after completion of the conversion.
-   *
-   * About the macro ID: When a macro is created in a new version of content, Confluence will generate a random ID for
-   * it, unless an ID is specified (by an app). The macro ID will look similar to this:
-   * '884bd9-0cb8-41d5-98be-f80943c14f96'. The ID is then persisted as new versions of content are created, and is only
-   * modified by Confluence if there are conflicting IDs.
-   *
-   * For Forge macros, the value for macro ID is the "local ID" of that particular ADF node. This value can be retrieved
-   * either client-side by calling view.getContext() and accessing "localId" on the resulting object, or server-side by
-   * examining the "local-id" parameter node inside the "parameters" node.
-   *
-   * Note that there are other attributes named "local-id", but only this particular one is used to store the macro ID.
-   *
-   * Example:  com.atlassian.ecosystem 
-   * e9c4aa10-73fa-417c-888d-48c719ae4165 
-   * 
-   *
-   * Note, to preserve backwards compatibility this resource will also match on the hash of the macro body, even if a
-   * macro ID is found. This check will eventually become redundant, as macro IDs are generated for pages and
-   * transparently propagate out to all instances.
-   *
-   * This backwards compatibility logic does not apply to Forge macros; those can only be retrieved by their ID.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to view the content that the
-   * macro is in.
-   */
-  async getAndAsyncConvertMacroBodyByMacroId(
-    parameters: Parameters.GetAndAsyncConvertMacroBodyByMacroId,
-    callback: Callback,
-  ): Promise;
-  /**
-   * Returns Async Id of the conversion task which will convert the macro into a content body of the desired format. The
-   * result will be available for 5 minutes after completion of the conversion.
-   *
-   * About the macro ID: When a macro is created in a new version of content, Confluence will generate a random ID for
-   * it, unless an ID is specified (by an app). The macro ID will look similar to this:
-   * '884bd9-0cb8-41d5-98be-f80943c14f96'. The ID is then persisted as new versions of content are created, and is only
-   * modified by Confluence if there are conflicting IDs.
-   *
-   * For Forge macros, the value for macro ID is the "local ID" of that particular ADF node. This value can be retrieved
-   * either client-side by calling view.getContext() and accessing "localId" on the resulting object, or server-side by
-   * examining the "local-id" parameter node inside the "parameters" node.
-   *
-   * Note that there are other attributes named "local-id", but only this particular one is used to store the macro ID.
-   *
-   * Example:  com.atlassian.ecosystem 
-   * e9c4aa10-73fa-417c-888d-48c719ae4165 
-   * 
-   *
-   * Note, to preserve backwards compatibility this resource will also match on the hash of the macro body, even if a
-   * macro ID is found. This check will eventually become redundant, as macro IDs are generated for pages and
-   * transparently propagate out to all instances.
-   *
-   * This backwards compatibility logic does not apply to Forge macros; those can only be retrieved by their ID.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to view the content that the
-   * macro is in.
-   */
-  async getAndAsyncConvertMacroBodyByMacroId(
-    parameters: Parameters.GetAndAsyncConvertMacroBodyByMacroId,
-    callback?: never,
-  ): Promise;
-  async getAndAsyncConvertMacroBodyByMacroId(
-    parameters: Parameters.GetAndAsyncConvertMacroBodyByMacroId,
-    callback?: Callback,
-  ): Promise {
-    const config: RequestConfig = {
-      url: `/api/content/${parameters.id}/history/${parameters.version}/macro/id/${parameters.macroId}/convert/async/${parameters.to}`,
-      method: 'GET',
-      params: {
-        allowCache: parameters.allowCache,
-        spaceKeyContext: parameters.spaceKeyContext,
-        embeddedContentRender: parameters.embeddedContentRender,
-        expand: parameters.expand,
-      },
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-}
diff --git a/src/api/contentPermissions.ts b/src/api/contentPermissions.ts
deleted file mode 100644
index 87283425..00000000
--- a/src/api/contentPermissions.ts
+++ /dev/null
@@ -1,61 +0,0 @@
-import type * as Models from './models';
-import type * as Parameters from './parameters';
-import type { Client } from '../clients';
-import type { Callback } from '../callback';
-import type { RequestConfig } from '../requestConfig';
-
-export class ContentPermissions {
-  constructor(private client: Client) {}
-
-  /**
-   * Check if a user or a group can perform an operation to the specified content. The `operation` to check must be
-   * provided. The user’s account ID or the ID of the group can be provided in the `subject` to check permissions
-   * against a specified user or group. The following permission checks are done to make sure that the user or group has
-   * the proper access:
-   *
-   * - Site permissions
-   * - Space permissions
-   * - Content restrictions
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to access the Confluence site
-   * ('Can use' global permission) if checking permission for self, otherwise 'Confluence Administrator' global
-   * permission is required.
-   */
-  async checkContentPermission(
-    parameters: Parameters.CheckContentPermission,
-    callback: Callback,
-  ): Promise;
-  /**
-   * Check if a user or a group can perform an operation to the specified content. The `operation` to check must be
-   * provided. The user’s account ID or the ID of the group can be provided in the `subject` to check permissions
-   * against a specified user or group. The following permission checks are done to make sure that the user or group has
-   * the proper access:
-   *
-   * - Site permissions
-   * - Space permissions
-   * - Content restrictions
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to access the Confluence site
-   * ('Can use' global permission) if checking permission for self, otherwise 'Confluence Administrator' global
-   * permission is required.
-   */
-  async checkContentPermission(
-    parameters: Parameters.CheckContentPermission,
-    callback?: never,
-  ): Promise;
-  async checkContentPermission(
-    parameters: Parameters.CheckContentPermission,
-    callback?: Callback,
-  ): Promise {
-    const config: RequestConfig = {
-      url: `/api/content/${parameters.id}/permission/check`,
-      method: 'POST',
-      data: {
-        subject: parameters.subject,
-        operation: parameters.operation,
-      },
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-}
diff --git a/src/api/contentProperties.ts b/src/api/contentProperties.ts
deleted file mode 100644
index 109ff46d..00000000
--- a/src/api/contentProperties.ts
+++ /dev/null
@@ -1,274 +0,0 @@
-import type * as Models from './models';
-import type * as Parameters from './parameters';
-import type { Callback } from '../callback';
-import type { Client } from '../clients';
-import type { RequestConfig } from '../requestConfig';
-
-/** @deprecated Will be removed in next major version. */
-export class ContentProperties {
-  constructor(private client: Client) {}
-
-  /**
-   * Returns the properties for a piece of content. For more information about content properties, see [Confluence
-   * entity properties](https://developer.atlassian.com/cloud/confluence/confluence-entity-properties/).
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'View' permission for the space, and
-   * permission to view the content if it is a page.
-   *
-   * @deprecated Will be removed in next major version.
-   */
-  async getContentProperties(
-    parameters: Parameters.GetContentProperties,
-    callback: Callback,
-  ): Promise;
-  /**
-   * Returns the properties for a piece of content. For more information about content properties, see [Confluence
-   * entity properties](https://developer.atlassian.com/cloud/confluence/confluence-entity-properties/).
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'View' permission for the space, and
-   * permission to view the content if it is a page.
-   *
-   * @deprecated Will be removed in next major version.
-   */
-  async getContentProperties(
-    parameters: Parameters.GetContentProperties,
-    callback?: never,
-  ): Promise;
-  async getContentProperties(
-    parameters: Parameters.GetContentProperties,
-    callback?: Callback,
-  ): Promise {
-    const config: RequestConfig = {
-      url: `/api/content/${parameters.id}/property`,
-      method: 'GET',
-      params: {
-        key: parameters.key,
-        expand: parameters.expand,
-        start: parameters.start,
-        limit: parameters.limit,
-      },
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-
-  /**
-   * Creates a property for an existing piece of content. For more information about content properties, see [Confluence
-   * entity properties](https://developer.atlassian.com/cloud/confluence/confluence-entity-properties/).
-   *
-   * This is the same as [Create content property for key](#api-content-id-property-key-post) except that the key is
-   * specified in the request body instead of as a path parameter.
-   *
-   * Content properties can also be added when creating a new piece of content by including them in the
-   * `metadata.properties` of the request.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to update the content.
-   *
-   * @deprecated Will be removed in next major version.
-   */
-  async createContentProperty(
-    parameters: Parameters.CreateContentProperty,
-    callback: Callback,
-  ): Promise;
-  /**
-   * Creates a property for an existing piece of content. For more information about content properties, see [Confluence
-   * entity properties](https://developer.atlassian.com/cloud/confluence/confluence-entity-properties/).
-   *
-   * This is the same as [Create content property for key](#api-content-id-property-key-post) except that the key is
-   * specified in the request body instead of as a path parameter.
-   *
-   * Content properties can also be added when creating a new piece of content by including them in the
-   * `metadata.properties` of the request.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to update the content.
-   *
-   * @deprecated Will be removed in next major version.
-   */
-  async createContentProperty(
-    parameters: Parameters.CreateContentProperty,
-    callback?: never,
-  ): Promise;
-  async createContentProperty(
-    parameters: Parameters.CreateContentProperty,
-    callback?: Callback,
-  ): Promise {
-    const config: RequestConfig = {
-      url: `/api/content/${parameters.id}/property`,
-      method: 'POST',
-      data: {
-        key: parameters.key,
-        value: parameters.value,
-      },
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-
-  /**
-   * Returns a content property for a piece of content. For more information, see [Confluence entity
-   * properties](https://developer.atlassian.com/cloud/confluence/confluence-entity-properties/).
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'View' permission for the space, and
-   * permission to view the content if it is a page.
-   *
-   * @deprecated Will be removed in next major version.
-   */
-  async getContentProperty(
-    parameters: Parameters.GetContentProperty,
-    callback: Callback,
-  ): Promise;
-  /**
-   * Returns a content property for a piece of content. For more information, see [Confluence entity
-   * properties](https://developer.atlassian.com/cloud/confluence/confluence-entity-properties/).
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'View' permission for the space, and
-   * permission to view the content if it is a page.
-   *
-   * @deprecated Will be removed in next major version.
-   */
-  async getContentProperty(
-    parameters: Parameters.GetContentProperty,
-    callback?: never,
-  ): Promise;
-  async getContentProperty(
-    parameters: Parameters.GetContentProperty,
-    callback?: Callback,
-  ): Promise {
-    const config: RequestConfig = {
-      url: `/api/content/${parameters.id}/property/${parameters.key}`,
-      method: 'GET',
-      params: {
-        expand: parameters.expand,
-        status: parameters.status,
-      },
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-
-  /**
-   * Creates a property for an existing piece of content. For more information about content properties, see [Confluence
-   * entity properties](https://developer.atlassian.com/cloud/confluence/confluence-entity-properties/).
-   *
-   * This is the same as [Create content property](#api-content-id-property-post) except that the key is specified as a
-   * path parameter instead of in the request body.
-   *
-   * Content properties can also be added when creating a new piece of content by including them in the
-   * `metadata.properties` of the request.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to update the content.
-   *
-   * @deprecated Will be removed in next major version.
-   */
-  async createContentPropertyForKey(
-    parameters: Parameters.CreateContentPropertyForKey,
-    callback: Callback,
-  ): Promise;
-  /**
-   * Creates a property for an existing piece of content. For more information about content properties, see [Confluence
-   * entity properties](https://developer.atlassian.com/cloud/confluence/confluence-entity-properties/).
-   *
-   * This is the same as [Create content property](#api-content-id-property-post) except that the key is specified as a
-   * path parameter instead of in the request body.
-   *
-   * Content properties can also be added when creating a new piece of content by including them in the
-   * `metadata.properties` of the request.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to update the content.
-   *
-   * @deprecated Will be removed in next major version.
-   */
-  async createContentPropertyForKey(
-    parameters: Parameters.CreateContentPropertyForKey,
-    callback?: never,
-  ): Promise;
-  async createContentPropertyForKey(
-    parameters: Parameters.CreateContentPropertyForKey,
-    callback?: Callback,
-  ): Promise {
-    const config: RequestConfig = {
-      url: `/api/content/${parameters.id}/property/${parameters.key}`,
-      method: 'POST',
-      data: {
-        value: parameters.value,
-      },
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-
-  /**
-   * Updates an existing content property. This method will also create a new property for a piece of content, if the
-   * property key does not exist and the property version is 1. For more information about content properties, see
-   * [Confluence entity properties](https://developer.atlassian.com/cloud/confluence/confluence-entity-properties/).
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to update the content.
-   *
-   * @deprecated Will be removed in next major version.
-   */
-  async updateContentProperty(
-    parameters: Parameters.UpdateContentProperty,
-    callback: Callback,
-  ): Promise;
-  /**
-   * Updates an existing content property. This method will also create a new property for a piece of content, if the
-   * property key does not exist and the property version is 1. For more information about content properties, see
-   * [Confluence entity properties](https://developer.atlassian.com/cloud/confluence/confluence-entity-properties/).
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to update the content.
-   *
-   * @deprecated Will be removed in next major version.
-   */
-  async updateContentProperty(
-    parameters: Parameters.UpdateContentProperty,
-    callback?: never,
-  ): Promise;
-  async updateContentProperty(
-    parameters: Parameters.UpdateContentProperty,
-    callback?: Callback,
-  ): Promise {
-    const config: RequestConfig = {
-      url: `/api/content/${parameters.id}/property/${parameters.key}`,
-      method: 'PUT',
-      data: {
-        value: parameters.value,
-        version: parameters.version,
-      },
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-
-  /**
-   * Deletes a content property. For more information about content properties, see [Confluence entity
-   * properties](https://developer.atlassian.com/cloud/confluence/confluence-entity-properties/).
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to update the content.
-   *
-   * @deprecated Will be removed in next major version.
-   */
-  async deleteContentProperty(
-    parameters: Parameters.DeleteContentProperty,
-    callback: Callback,
-  ): Promise;
-  /**
-   * Deletes a content property. For more information about content properties, see [Confluence entity
-   * properties](https://developer.atlassian.com/cloud/confluence/confluence-entity-properties/).
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to update the content.
-   *
-   * @deprecated Will be removed in next major version.
-   */
-  async deleteContentProperty(parameters: Parameters.DeleteContentProperty, callback?: never): Promise;
-  async deleteContentProperty(
-    parameters: Parameters.DeleteContentProperty,
-    callback?: Callback,
-  ): Promise {
-    const config: RequestConfig = {
-      url: `/api/content/${parameters.id}/property/${parameters.key}`,
-      method: 'DELETE',
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-}
diff --git a/src/api/contentRestrictions.ts b/src/api/contentRestrictions.ts
deleted file mode 100644
index ef8346ad..00000000
--- a/src/api/contentRestrictions.ts
+++ /dev/null
@@ -1,558 +0,0 @@
-import type * as Models from './models';
-import type * as Parameters from './parameters';
-import type { Client } from '../clients';
-import type { Callback } from '../callback';
-import type { RequestConfig } from '../requestConfig';
-
-export class ContentRestrictions {
-  constructor(private client: Client) {}
-
-  /**
-   * Returns the restrictions on a piece of content.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to view the content.
-   */
-  async getRestrictions(
-    parameters: Parameters.GetRestrictions,
-    callback: Callback,
-  ): Promise;
-  /**
-   * Returns the restrictions on a piece of content.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to view the content.
-   */
-  async getRestrictions(
-    parameters: Parameters.GetRestrictions,
-    callback?: never,
-  ): Promise;
-  async getRestrictions(
-    parameters: Parameters.GetRestrictions,
-    callback?: Callback,
-  ): Promise {
-    const config: RequestConfig = {
-      url: `/api/content/${parameters.id}/restriction`,
-      method: 'GET',
-      params: {
-        expand: parameters.expand,
-        start: parameters.start,
-        limit: parameters.limit,
-      },
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-
-  /**
-   * Adds restrictions to a piece of content. Note, this does not change any existing restrictions on the content.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to edit the content.
-   */
-  async addRestrictions(
-    parameters: Parameters.AddRestrictions,
-    callback: Callback,
-  ): Promise;
-  /**
-   * Adds restrictions to a piece of content. Note, this does not change any existing restrictions on the content.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to edit the content.
-   */
-  async addRestrictions(
-    parameters: Parameters.AddRestrictions,
-    callback?: never,
-  ): Promise;
-  async addRestrictions(
-    parameters: Parameters.AddRestrictions,
-    callback?: Callback,
-  ): Promise {
-    const config: RequestConfig = {
-      url: `/api/content/${parameters.id}/restriction`,
-      method: 'POST',
-      params: {
-        expand: parameters.expand,
-      },
-      data: parameters.body,
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-
-  /**
-   * Updates restrictions for a piece of content. This removes the existing restrictions and replaces them with the
-   * restrictions in the request.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to edit the content.
-   */
-  async updateRestrictions(
-    parameters: Parameters.UpdateRestrictions,
-    callback: Callback,
-  ): Promise;
-  /**
-   * Updates restrictions for a piece of content. This removes the existing restrictions and replaces them with the
-   * restrictions in the request.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to edit the content.
-   */
-  async updateRestrictions(
-    parameters: Parameters.UpdateRestrictions,
-    callback?: never,
-  ): Promise;
-  async updateRestrictions(
-    parameters: Parameters.UpdateRestrictions,
-    callback?: Callback,
-  ): Promise {
-    const config: RequestConfig = {
-      url: `/api/content/${parameters.id}/restriction`,
-      method: 'PUT',
-      params: {
-        expand: parameters.expand,
-      },
-      data: parameters.body,
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-
-  /**
-   * Removes all restrictions (read and update) on a piece of content.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to edit the content.
-   */
-  async deleteRestrictions(
-    parameters: Parameters.DeleteRestrictions,
-    callback: Callback,
-  ): Promise;
-  /**
-   * Removes all restrictions (read and update) on a piece of content.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to edit the content.
-   */
-  async deleteRestrictions(
-    parameters: Parameters.DeleteRestrictions,
-    callback?: never,
-  ): Promise;
-  async deleteRestrictions(
-    parameters: Parameters.DeleteRestrictions,
-    callback?: Callback,
-  ): Promise {
-    const config: RequestConfig = {
-      url: `/api/content/${parameters.id}/restriction`,
-      method: 'DELETE',
-      params: {
-        expand: parameters.expand,
-      },
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-
-  /**
-   * Returns restrictions on a piece of content by operation. This method is similar to [Get
-   * restrictions](#api-content-id-restriction-get) except that the operations are properties of the return object,
-   * rather than items in a results array.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to view the content.
-   */
-  async getRestrictionsByOperation(
-    parameters: Parameters.GetRestrictionsByOperation,
-    callback: Callback,
-  ): Promise;
-  /**
-   * Returns restrictions on a piece of content by operation. This method is similar to [Get
-   * restrictions](#api-content-id-restriction-get) except that the operations are properties of the return object,
-   * rather than items in a results array.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to view the content.
-   */
-  async getRestrictionsByOperation(
-    parameters: Parameters.GetRestrictionsByOperation,
-    callback?: never,
-  ): Promise;
-  async getRestrictionsByOperation(
-    parameters: Parameters.GetRestrictionsByOperation,
-    callback?: Callback,
-  ): Promise {
-    const config: RequestConfig = {
-      url: `/api/content/${parameters.id}/restriction/byOperation`,
-      method: 'GET',
-      params: {
-        expand: parameters.expand,
-      },
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-
-  /**
-   * Returns the restictions on a piece of content for a given operation (read or update).
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to view the content.
-   */
-  async getRestrictionsForOperation(
-    parameters: Parameters.GetRestrictionsForOperation,
-    callback: Callback,
-  ): Promise;
-  /**
-   * Returns the restictions on a piece of content for a given operation (read or update).
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to view the content.
-   */
-  async getRestrictionsForOperation(
-    parameters: Parameters.GetRestrictionsForOperation,
-    callback?: never,
-  ): Promise;
-  async getRestrictionsForOperation(
-    parameters: Parameters.GetRestrictionsForOperation,
-    callback?: Callback,
-  ): Promise {
-    const config: RequestConfig = {
-      url: `/api/content/${parameters.id}/restriction/byOperation/${parameters.operationKey}`,
-      method: 'GET',
-      params: {
-        expand: parameters.expand,
-        start: parameters.start,
-        limit: parameters.limit,
-      },
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-
-  /**
-   * Returns whether the specified content restriction applies to a group. For example, if a page with `id=123` has a
-   * `read` restriction for the `admins` group, the following request will return `true`:
-   *
-   * `https://your-domain.atlassian.net/api/content/123/restriction/byOperation/read/group/admins`
-   *
-   * Note that a response of `true` does not guarantee that the group can view the page, as it does not account for
-   * account-inherited restrictions, space permissions, or even product access. For more information, see [Confluence
-   * permissions](https://confluence.atlassian.com/x/_AozKw).
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to view the content.
-   *
-   * @deprecated Will be removed in next major version.
-   */
-  async getContentRestrictionStatusForGroup(
-    parameters: Parameters.GetContentRestrictionStatusForGroup,
-    callback: Callback,
-  ): Promise;
-  /**
-   * Returns whether the specified content restriction applies to a group. For example, if a page with `id=123` has a
-   * `read` restriction for the `admins` group, the following request will return `true`:
-   *
-   * `https://your-domain.atlassian.net/api/content/123/restriction/byOperation/read/group/admins`
-   *
-   * Note that a response of `true` does not guarantee that the group can view the page, as it does not account for
-   * account-inherited restrictions, space permissions, or even product access. For more information, see [Confluence
-   * permissions](https://confluence.atlassian.com/x/_AozKw).
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to view the content.
-   *
-   * @deprecated Will be removed in next major version.
-   */
-  async getContentRestrictionStatusForGroup(
-    parameters: Parameters.GetContentRestrictionStatusForGroup,
-    callback?: never,
-  ): Promise;
-  async getContentRestrictionStatusForGroup(
-    parameters: Parameters.GetContentRestrictionStatusForGroup,
-    callback?: Callback,
-  ): Promise {
-    const config: RequestConfig = {
-      url: `/api/content/${parameters.id}/restriction/byOperation/${parameters.operationKey}/group/${parameters.groupName}`,
-      method: 'GET',
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-
-  /**
-   * Adds a group to a content restriction. That is, grant read or update permission to the group for a piece of
-   * content.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to edit the content.
-   *
-   * @deprecated Will be removed in next major version.
-   */
-  async addGroupToContentRestriction(
-    parameters: Parameters.AddGroupToContentRestriction,
-    callback: Callback,
-  ): Promise;
-  /**
-   * Adds a group to a content restriction. That is, grant read or update permission to the group for a piece of
-   * content.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to edit the content.
-   *
-   * @deprecated Will be removed in next major version.
-   */
-  async addGroupToContentRestriction(
-    parameters: Parameters.AddGroupToContentRestriction,
-    callback?: never,
-  ): Promise;
-  async addGroupToContentRestriction(
-    parameters: Parameters.AddGroupToContentRestriction,
-    callback?: Callback,
-  ): Promise {
-    const config: RequestConfig = {
-      url: `/api/content/${parameters.id}/restriction/byOperation/${parameters.operationKey}/group/${parameters.groupName}`,
-      method: 'PUT',
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-
-  /**
-   * Removes a group from a content restriction. That is, remove read or update permission for the group for a piece of
-   * content.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to edit the content.
-   *
-   * @deprecated Will be removed in next major version.
-   */
-  async removeGroupByName(parameters: Parameters.RemoveGroupByName, callback: Callback): Promise;
-  /**
-   * Removes a group from a content restriction. That is, remove read or update permission for the group for a piece of
-   * content.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to edit the content.
-   *
-   * @deprecated Will be removed in next major version.
-   */
-  async removeGroupByName(parameters: Parameters.RemoveGroupByName, callback?: never): Promise;
-  async removeGroupByName(
-    parameters: Parameters.RemoveGroupByName,
-    callback?: Callback,
-  ): Promise {
-    const config: RequestConfig = {
-      url: `/api/content/${parameters.id}/restriction/byOperation/${parameters.operationKey}/group/${parameters.groupName}`,
-      method: 'DELETE',
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-
-  /**
-   * Returns whether the specified content restriction applies to a group. For example, if a page with `id=123` has a
-   * `read` restriction for the `123456` group id, the following request will return `true`:
-   *
-   * `https://your-domain.atlassian.net/api/content/123/restriction/byOperation/read/byGroupId/123456`
-   *
-   * Note that a response of `true` does not guarantee that the group can view the page, as it does not account for
-   * account-inherited restrictions, space permissions, or even product access. For more information, see [Confluence
-   * permissions](https://confluence.atlassian.com/x/_AozKw).
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to view the content.
-   */
-  async getIndividualGroupRestrictionStatusByGroupId(
-    parameters: Parameters.GetIndividualGroupRestrictionStatusByGroupId,
-    callback: Callback,
-  ): Promise;
-  /**
-   * Returns whether the specified content restriction applies to a group. For example, if a page with `id=123` has a
-   * `read` restriction for the `123456` group id, the following request will return `true`:
-   *
-   * `https://your-domain.atlassian.net/api/content/123/restriction/byOperation/read/byGroupId/123456`
-   *
-   * Note that a response of `true` does not guarantee that the group can view the page, as it does not account for
-   * account-inherited restrictions, space permissions, or even product access. For more information, see [Confluence
-   * permissions](https://confluence.atlassian.com/x/_AozKw).
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to view the content.
-   */
-  async getIndividualGroupRestrictionStatusByGroupId(
-    parameters: Parameters.GetIndividualGroupRestrictionStatusByGroupId,
-    callback?: never,
-  ): Promise;
-  async getIndividualGroupRestrictionStatusByGroupId(
-    parameters: Parameters.GetIndividualGroupRestrictionStatusByGroupId,
-    callback?: Callback,
-  ): Promise {
-    const config: RequestConfig = {
-      url: `/api/content/${parameters.id}/restriction/byOperation/${parameters.operationKey}/byGroupId/${parameters.groupId}`,
-      method: 'GET',
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-
-  /**
-   * Adds a group to a content restriction by Group Id. That is, grant read or update permission to the group for a
-   * piece of content.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to edit the content.
-   */
-  async addGroupToContentRestrictionByGroupId(
-    parameters: Parameters.AddGroupToContentRestrictionByGroupId,
-    callback: Callback,
-  ): Promise;
-  /**
-   * Adds a group to a content restriction by Group Id. That is, grant read or update permission to the group for a
-   * piece of content.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to edit the content.
-   */
-  async addGroupToContentRestrictionByGroupId(
-    parameters: Parameters.AddGroupToContentRestrictionByGroupId,
-    callback?: never,
-  ): Promise;
-  async addGroupToContentRestrictionByGroupId(
-    parameters: Parameters.AddGroupToContentRestrictionByGroupId,
-    callback?: Callback,
-  ): Promise {
-    const config: RequestConfig = {
-      url: `/api/content/${parameters.id}/restriction/byOperation/${parameters.operationKey}/byGroupId/${parameters.groupId}`,
-      method: 'PUT',
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-
-  /**
-   * Removes a group from a content restriction. That is, remove read or update permission for the group for a piece of
-   * content.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to edit the content.
-   */
-  async removeGroupById(parameters: Parameters.RemoveGroupById, callback: Callback): Promise;
-  /**
-   * Removes a group from a content restriction. That is, remove read or update permission for the group for a piece of
-   * content.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to edit the content.
-   */
-  async removeGroupById(parameters: Parameters.RemoveGroupById, callback?: never): Promise;
-  async removeGroupById(
-    parameters: Parameters.RemoveGroupById,
-    callback?: Callback,
-  ): Promise {
-    const config: RequestConfig = {
-      url: `/api/content/${parameters.id}/restriction/byOperation/${parameters.operationKey}/byGroupId/${parameters.groupId}`,
-      method: 'DELETE',
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-
-  /**
-   * Returns whether the specified content restriction applies to a user. For example, if a page with `id=123` has a
-   * `read` restriction for a user with an account ID of `384093:32b4d9w0-f6a5-3535-11a3-9c8c88d10192`, the following
-   * request will return `true`:
-   *
-   * `https://your-domain.atlassian.net/api/content/123/restriction/byOperation/read/user?accountId=384093:32b4d9w0-f6a5-3535-11a3-9c8c88d10192`
-   *
-   * Note that a response of `true` does not guarantee that the user can view the page, as it does not account for
-   * account-inherited restrictions, space permissions, or even product access. For more information, see [Confluence
-   * permissions](https://confluence.atlassian.com/x/_AozKw).
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to view the content.
-   */
-  async getContentRestrictionStatusForUser(
-    parameters: Parameters.GetContentRestrictionStatusForUser,
-    callback: Callback,
-  ): Promise;
-  /**
-   * Returns whether the specified content restriction applies to a user. For example, if a page with `id=123` has a
-   * `read` restriction for a user with an account ID of `384093:32b4d9w0-f6a5-3535-11a3-9c8c88d10192`, the following
-   * request will return `true`:
-   *
-   * `https://your-domain.atlassian.net/api/content/123/restriction/byOperation/read/user?accountId=384093:32b4d9w0-f6a5-3535-11a3-9c8c88d10192`
-   *
-   * Note that a response of `true` does not guarantee that the user can view the page, as it does not account for
-   * account-inherited restrictions, space permissions, or even product access. For more information, see [Confluence
-   * permissions](https://confluence.atlassian.com/x/_AozKw).
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to view the content.
-   */
-  async getContentRestrictionStatusForUser(
-    parameters: Parameters.GetContentRestrictionStatusForUser,
-    callback?: never,
-  ): Promise;
-  async getContentRestrictionStatusForUser(
-    parameters: Parameters.GetContentRestrictionStatusForUser,
-    callback?: Callback,
-  ): Promise {
-    const config: RequestConfig = {
-      url: `/api/content/${parameters.id}/restriction/byOperation/${parameters.operationKey}/user`,
-      method: 'GET',
-      params: {
-        key: parameters.key,
-        userName: parameters.userName,
-        accountId: parameters.accountId,
-      },
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-
-  /**
-   * Adds a user to a content restriction. That is, grant read or update permission to the user for a piece of content.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to edit the content.
-   */
-  async addUserToContentRestriction(
-    parameters: Parameters.AddUserToContentRestriction,
-    callback: Callback,
-  ): Promise;
-  /**
-   * Adds a user to a content restriction. That is, grant read or update permission to the user for a piece of content.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to edit the content.
-   */
-  async addUserToContentRestriction(
-    parameters: Parameters.AddUserToContentRestriction,
-    callback?: never,
-  ): Promise;
-  async addUserToContentRestriction(
-    parameters: Parameters.AddUserToContentRestriction,
-    callback?: Callback,
-  ): Promise {
-    const config: RequestConfig = {
-      url: `/api/content/${parameters.id}/restriction/byOperation/${parameters.operationKey}/user`,
-      method: 'PUT',
-      params: {
-        key: parameters.key,
-        userName: parameters.userName,
-        accountId: parameters.accountId,
-      },
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-
-  /**
-   * Removes a group from a content restriction. That is, remove read or update permission for the group for a piece of
-   * content.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to edit the content.
-   */
-  async removeUserFromContentRestriction(
-    parameters: Parameters.RemoveUserFromContentRestriction,
-    callback: Callback,
-  ): Promise;
-  /**
-   * Removes a group from a content restriction. That is, remove read or update permission for the group for a piece of
-   * content.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to edit the content.
-   */
-  async removeUserFromContentRestriction(
-    parameters: Parameters.RemoveUserFromContentRestriction,
-    callback?: never,
-  ): Promise;
-  async removeUserFromContentRestriction(
-    parameters: Parameters.RemoveUserFromContentRestriction,
-    callback?: Callback,
-  ): Promise {
-    const config: RequestConfig = {
-      url: `/api/content/${parameters.id}/restriction/byOperation/${parameters.operationKey}/user`,
-      method: 'DELETE',
-      params: {
-        key: parameters.key,
-        userName: parameters.userName,
-        accountId: parameters.accountId,
-      },
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-}
diff --git a/src/api/contentStates.ts b/src/api/contentStates.ts
deleted file mode 100644
index ce2f69ff..00000000
--- a/src/api/contentStates.ts
+++ /dev/null
@@ -1,294 +0,0 @@
-import type * as Models from './models';
-import type * as Parameters from './parameters';
-import type { Client } from '../clients';
-import type { Callback } from '../callback';
-import type { RequestConfig } from '../requestConfig';
-
-export class ContentStates {
-  constructor(private client: Client) {}
-
-  /**
-   * Gets the current content state of the draft or current version of content. To specify the draft version, set the
-   * parameter status to draft, otherwise archived or current will get the relevant published state.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to view the content.
-   */
-  async getContentState(
-    parameters: Parameters.GetContentState,
-    callback: Callback,
-  ): Promise;
-  /**
-   * Gets the current content state of the draft or current version of content. To specify the draft version, set the
-   * parameter status to draft, otherwise archived or current will get the relevant published state.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to view the content.
-   */
-  async getContentState(
-    parameters: Parameters.GetContentState,
-    callback?: never,
-  ): Promise;
-  async getContentState(
-    parameters: Parameters.GetContentState,
-    callback?: Callback,
-  ): Promise {
-    const config: RequestConfig = {
-      url: `/api/content/${parameters.id}/state`,
-      method: 'GET',
-      params: {
-        status: parameters.status,
-      },
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-
-  /**
-   * Sets the content state of the content specified and creates a new version (publishes the content without changing
-   * the body) of the content with the new state.
-   *
-   * You may pass in either an id of a state, or the name and color of a desired new state. If all 3 are passed in, id
-   * will be used. If the name and color passed in already exist under the current user's existing custom states, the
-   * existing state will be reused. If custom states are disabled in the space of the content (which can be determined
-   * by getting the content state space settings of the content's space) then this set will fail.
-   *
-   * You may not remove a content state via this PUT request. You must use the DELETE method. A specified state is
-   * required in the body of this request.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to edit the content.
-   */
-  async setContentState(
-    parameters: Parameters.SetContentState,
-    callback: Callback,
-  ): Promise;
-  /**
-   * Sets the content state of the content specified and creates a new version (publishes the content without changing
-   * the body) of the content with the new state.
-   *
-   * You may pass in either an id of a state, or the name and color of a desired new state. If all 3 are passed in, id
-   * will be used. If the name and color passed in already exist under the current user's existing custom states, the
-   * existing state will be reused. If custom states are disabled in the space of the content (which can be determined
-   * by getting the content state space settings of the content's space) then this set will fail.
-   *
-   * You may not remove a content state via this PUT request. You must use the DELETE method. A specified state is
-   * required in the body of this request.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to edit the content.
-   */
-  async setContentState(
-    parameters: Parameters.SetContentState,
-    callback?: never,
-  ): Promise;
-  async setContentState(
-    parameters: Parameters.SetContentState,
-    callback?: Callback,
-  ): Promise {
-    const config: RequestConfig = {
-      url: `/api/content/${parameters.id}/state`,
-      method: 'PUT',
-      params: {
-        status: parameters.status,
-      },
-      data: {
-        name: parameters.name,
-        color: parameters.color,
-        id: parameters.stateId,
-      },
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-
-  /**
-   * Removes the content state of the content specified and creates a new version (publishes the content without
-   * changing the body) of the content with the new status.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to edit the content.
-   */
-  async removeContentState(
-    parameters: Parameters.RemoveContentState,
-    callback: Callback,
-  ): Promise;
-  /**
-   * Removes the content state of the content specified and creates a new version (publishes the content without
-   * changing the body) of the content with the new status.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to edit the content.
-   */
-  async removeContentState(
-    parameters: Parameters.RemoveContentState,
-    callback?: never,
-  ): Promise;
-  async removeContentState(
-    parameters: Parameters.RemoveContentState,
-    callback?: Callback,
-  ): Promise {
-    const config: RequestConfig = {
-      url: `/api/content/${parameters.id}/state`,
-      method: 'DELETE',
-      params: {
-        status: parameters.status,
-      },
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-
-  /**
-   * Gets content states that are available for the content to be set as. Will return all enabled Space Content States.
-   * Will only return most the 3 most recently published custom content states to match UI editor list. To get all
-   * custom content states, use the /content-states endpoint.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to edit the content.
-   */
-  async getAvailableContentStates(
-    parameters: Parameters.GetAvailableContentStates,
-    callback: Callback,
-  ): Promise;
-  /**
-   * Gets content states that are available for the content to be set as. Will return all enabled Space Content States.
-   * Will only return most the 3 most recently published custom content states to match UI editor list. To get all
-   * custom content states, use the /content-states endpoint.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to edit the content.
-   */
-  async getAvailableContentStates(
-    parameters: Parameters.GetAvailableContentStates,
-    callback?: never,
-  ): Promise;
-  async getAvailableContentStates(
-    parameters: Parameters.GetAvailableContentStates,
-    callback?: Callback,
-  ): Promise {
-    const config: RequestConfig = {
-      url: `/api/content/${parameters.id}/state/available`,
-      method: 'GET',
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-
-  /**
-   * Get custom content states that authenticated user has created.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required** Must have user authentication.
-   */
-  async getCustomContentStates(callback: Callback): Promise;
-  /**
-   * Get custom content states that authenticated user has created.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required** Must have user authentication.
-   */
-  async getCustomContentStates(callback?: never): Promise;
-  async getCustomContentStates(callback?: Callback): Promise {
-    const config: RequestConfig = {
-      url: '/api/content-states',
-      method: 'GET',
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-
-  /**
-   * Get content states that are suggested in the space.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'View' permission for the space.
-   */
-  async getSpaceContentStates(
-    parameters: Parameters.GetSpaceContentStates,
-    callback: Callback,
-  ): Promise;
-  /**
-   * Get content states that are suggested in the space.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'View' permission for the space.
-   */
-  async getSpaceContentStates(
-    parameters: Parameters.GetSpaceContentStates,
-    callback?: never,
-  ): Promise;
-  async getSpaceContentStates(
-    parameters: Parameters.GetSpaceContentStates,
-    callback?: Callback,
-  ): Promise {
-    const config: RequestConfig = {
-      url: `/api/space/${parameters.spaceKey}/state`,
-      method: 'GET',
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-
-  /**
-   * Get object describing whether content states are allowed at all, if custom content states or space content states
-   * are restricted, and a list of space content states allowed for the space if they are not restricted.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'Admin' permission for the space.
-   */
-  async getContentStateSettings(
-    parameters: Parameters.GetContentStateSettings,
-    callback: Callback,
-  ): Promise;
-  /**
-   * Get object describing whether content states are allowed at all, if custom content states or space content states
-   * are restricted, and a list of space content states allowed for the space if they are not restricted.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'Admin' permission for the space.
-   */
-  async getContentStateSettings(
-    parameters: Parameters.GetContentStateSettings,
-    callback?: never,
-  ): Promise;
-  async getContentStateSettings(
-    parameters: Parameters.GetContentStateSettings,
-    callback?: Callback,
-  ): Promise {
-    const config: RequestConfig = {
-      url: `/api/space/${parameters.spaceKey}/state/settings`,
-      method: 'GET',
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-
-  /**
-   * Returns all content that has the provided content state in a space.
-   *
-   * If the expand query parameter is used with the `body.export_view` and/or `body.styled_view` properties, then the
-   * query limit parameter will be restricted to a maximum value of 25.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'View' permission for the space.
-   */
-  async getContentsWithState(
-    parameters: Parameters.GetContentsWithState,
-    callback: Callback,
-  ): Promise;
-  /**
-   * Returns all content that has the provided content state in a space.
-   *
-   * If the expand query parameter is used with the `body.export_view` and/or `body.styled_view` properties, then the
-   * query limit parameter will be restricted to a maximum value of 25.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'View' permission for the space.
-   */
-  async getContentsWithState(
-    parameters: Parameters.GetContentsWithState,
-    callback?: never,
-  ): Promise;
-  async getContentsWithState(
-    parameters: Parameters.GetContentsWithState,
-    callback?: Callback,
-  ): Promise {
-    const config: RequestConfig = {
-      url: `/api/space/${parameters.spaceKey}/state/content`,
-      method: 'GET',
-      params: {
-        'state-id': parameters.stateId,
-        expand: parameters.expand,
-        limit: parameters.limit,
-        start: parameters.start,
-      },
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-}
diff --git a/src/api/contentVersions.ts b/src/api/contentVersions.ts
deleted file mode 100644
index 29ef35c6..00000000
--- a/src/api/contentVersions.ts
+++ /dev/null
@@ -1,154 +0,0 @@
-import type * as Models from './models';
-import type * as Parameters from './parameters';
-import type { Client } from '../clients';
-import type { Callback } from '../callback';
-import type { RequestConfig } from '../requestConfig';
-
-export class ContentVersions {
-  constructor(private client: Client) {}
-
-  /**
-   * Returns the versions for a piece of content in descending order.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to view the content. If the
-   * content is a blog post, 'View' permission for the space is required.
-   *
-   * @deprecated Will be removed in next major version.
-   */
-  async getContentVersions(
-    parameters: Parameters.GetContentVersions,
-    callback: Callback,
-  ): Promise;
-  /**
-   * Returns the versions for a piece of content in descending order.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to view the content. If the
-   * content is a blog post, 'View' permission for the space is required.
-   *
-   * @deprecated Will be removed in next major version.
-   */
-  async getContentVersions(
-    parameters: Parameters.GetContentVersions,
-    callback?: never,
-  ): Promise;
-  async getContentVersions(
-    parameters: Parameters.GetContentVersions,
-    callback?: Callback,
-  ): Promise {
-    const config: RequestConfig = {
-      url: `/api/content/${parameters.id}/version`,
-      method: 'GET',
-      params: {
-        start: parameters.start,
-        limit: parameters.limit,
-        expand: parameters.expand,
-      },
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-
-  /**
-   * Restores a historical version to be the latest version. That is, a new version is created with the content of the
-   * historical version.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to update the content.
-   */
-  async restoreContentVersion(
-    parameters: Parameters.RestoreContentVersion,
-    callback: Callback,
-  ): Promise;
-  /**
-   * Restores a historical version to be the latest version. That is, a new version is created with the content of the
-   * historical version.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to update the content.
-   */
-  async restoreContentVersion(
-    parameters: Parameters.RestoreContentVersion,
-    callback?: never,
-  ): Promise;
-  async restoreContentVersion(
-    parameters: Parameters.RestoreContentVersion,
-    callback?: Callback,
-  ): Promise {
-    const config: RequestConfig = {
-      url: `/api/content/${parameters.id}/version`,
-      method: 'POST',
-      params: {
-        expand: parameters.expand,
-      },
-      data: {
-        operationKey: parameters.operationKey,
-        params: parameters.params,
-      },
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-
-  /**
-   * Returns a version for a piece of content.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to view the content. If the
-   * content is a blog post, 'View' permission for the space is required.
-   *
-   * @deprecated Will be removed in next major version.
-   */
-  async getContentVersion(
-    parameters: Parameters.GetContentVersion,
-    callback: Callback,
-  ): Promise;
-  /**
-   * Returns a version for a piece of content.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to view the content. If the
-   * content is a blog post, 'View' permission for the space is required.
-   *
-   * @deprecated Will be removed in next major version.
-   */
-  async getContentVersion(parameters: Parameters.GetContentVersion, callback?: never): Promise;
-  async getContentVersion(
-    parameters: Parameters.GetContentVersion,
-    callback?: Callback,
-  ): Promise {
-    const config: RequestConfig = {
-      url: `/api/content/${parameters.id}/version/${parameters.versionNumber}`,
-      method: 'GET',
-      params: {
-        expand: parameters.expand,
-      },
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-
-  /**
-   * Delete a historical version. This does not delete the changes made to the content in that version, rather the
-   * changes for the deleted version are rolled up into the next version. Note, you cannot delete the current version.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to update the content.
-   */
-  async deleteContentVersion(
-    parameters: Parameters.DeleteContentVersion,
-    callback: Callback,
-  ): Promise;
-  /**
-   * Delete a historical version. This does not delete the changes made to the content in that version, rather the
-   * changes for the deleted version are rolled up into the next version. Note, you cannot delete the current version.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to update the content.
-   */
-  async deleteContentVersion(parameters: Parameters.DeleteContentVersion, callback?: never): Promise;
-  async deleteContentVersion(
-    parameters: Parameters.DeleteContentVersion,
-    callback?: Callback,
-  ): Promise {
-    const config: RequestConfig = {
-      url: `/api/content/${parameters.id}/version/${parameters.versionNumber}`,
-      method: 'DELETE',
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-}
diff --git a/src/api/contentWatches.ts b/src/api/contentWatches.ts
deleted file mode 100644
index 5c16d9b0..00000000
--- a/src/api/contentWatches.ts
+++ /dev/null
@@ -1,501 +0,0 @@
-import type * as Models from './models';
-import type * as Parameters from './parameters';
-import type { Client } from '../clients';
-import type { Callback } from '../callback';
-import type { RequestConfig } from '../requestConfig';
-
-export class ContentWatches {
-  constructor(private client: Client) {}
-
-  /**
-   * Returns the watches for a page. A user that watches a page will receive receive notifications when the page is
-   * updated.
-   *
-   * If you want to manage watches for a page, use the following `user` methods:
-   *
-   * - [Get content watch status for user](#api-user-watch-content-contentId-get)
-   * - [Add content watch](#api-user-watch-content-contentId-post)
-   * - [Remove content watch](#api-user-watch-content-contentId-delete)
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to access the Confluence site
-   * ('Can use' global permission).
-   */
-  async getWatchesForPage(
-    parameters: Parameters.GetWatchesForPage,
-    callback: Callback,
-  ): Promise;
-  /**
-   * Returns the watches for a page. A user that watches a page will receive receive notifications when the page is
-   * updated.
-   *
-   * If you want to manage watches for a page, use the following `user` methods:
-   *
-   * - [Get content watch status for user](#api-user-watch-content-contentId-get)
-   * - [Add content watch](#api-user-watch-content-contentId-post)
-   * - [Remove content watch](#api-user-watch-content-contentId-delete)
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to access the Confluence site
-   * ('Can use' global permission).
-   */
-  async getWatchesForPage(
-    parameters: Parameters.GetWatchesForPage,
-    callback?: never,
-  ): Promise;
-  async getWatchesForPage(
-    parameters: Parameters.GetWatchesForPage,
-    callback?: Callback,
-  ): Promise {
-    const config: RequestConfig = {
-      url: `/api/content/${parameters.id}/notification/child-created`,
-      method: 'GET',
-      params: {
-        start: parameters.start,
-        limit: parameters.limit,
-      },
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-
-  /**
-   * Returns all space watches for the space that the content is in. A user that watches a space will receive receive
-   * notifications when any content in the space is updated.
-   *
-   * If you want to manage watches for a space, use the following `user` methods:
-   *
-   * - [Get space watch status for user](#api-user-watch-space-spaceKey-get)
-   * - [Add space watch](#api-user-watch-space-spaceKey-post)
-   * - [Remove space watch](#api-user-watch-space-spaceKey-delete)
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to access the Confluence site
-   * ('Can use' global permission).
-   */
-  async getWatchesForSpace(
-    parameters: Parameters.GetWatchesForSpace,
-    callback: Callback,
-  ): Promise;
-  /**
-   * Returns all space watches for the space that the content is in. A user that watches a space will receive receive
-   * notifications when any content in the space is updated.
-   *
-   * If you want to manage watches for a space, use the following `user` methods:
-   *
-   * - [Get space watch status for user](#api-user-watch-space-spaceKey-get)
-   * - [Add space watch](#api-user-watch-space-spaceKey-post)
-   * - [Remove space watch](#api-user-watch-space-spaceKey-delete)
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to access the Confluence site
-   * ('Can use' global permission).
-   */
-  async getWatchesForSpace(
-    parameters: Parameters.GetWatchesForSpace,
-    callback?: never,
-  ): Promise;
-  async getWatchesForSpace(
-    parameters: Parameters.GetWatchesForSpace,
-    callback?: Callback,
-  ): Promise {
-    const config: RequestConfig = {
-      url: `/api/content/${parameters.id}/notification/created`,
-      method: 'GET',
-      params: {
-        start: parameters.start,
-        limit: parameters.limit,
-      },
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-
-  /** Returns a list of watchers of a space */
-  async getWatchersForSpace(
-    parameters: Parameters.GetWatchersForSpace,
-    callback: Callback,
-  ): Promise;
-  /** Returns a list of watchers of a space */
-  async getWatchersForSpace(
-    parameters: Parameters.GetWatchersForSpace,
-    callback?: never,
-  ): Promise;
-  async getWatchersForSpace(
-    parameters: Parameters.GetWatchersForSpace,
-    callback?: Callback,
-  ): Promise {
-    const config: RequestConfig = {
-      url: `/api/space/${parameters.spaceKey}/watch`,
-      method: 'GET',
-      params: {
-        start: parameters.start,
-        limit: parameters.limit,
-      },
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-
-  /**
-   * Returns whether a user is watching a piece of content. Choose the user by doing one of the following:
-   *
-   * - Specify a user via a query parameter: Use the `accountId` to identify the user.
-   * - Do not specify a user: The currently logged-in user will be used.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'Confluence Administrator' global permission
-   * if specifying a user, otherwise permission to access the Confluence site ('Can use' global permission).
-   */
-  async getContentWatchStatus(
-    parameters: Parameters.GetContentWatchStatus,
-    callback: Callback,
-  ): Promise;
-  /**
-   * Returns whether a user is watching a piece of content. Choose the user by doing one of the following:
-   *
-   * - Specify a user via a query parameter: Use the `accountId` to identify the user.
-   * - Do not specify a user: The currently logged-in user will be used.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'Confluence Administrator' global permission
-   * if specifying a user, otherwise permission to access the Confluence site ('Can use' global permission).
-   */
-  async getContentWatchStatus(
-    parameters: Parameters.GetContentWatchStatus,
-    callback?: never,
-  ): Promise;
-  async getContentWatchStatus(
-    parameters: Parameters.GetContentWatchStatus,
-    callback?: Callback,
-  ): Promise {
-    const config: RequestConfig = {
-      url: `/api/user/watch/content/${parameters.contentId}`,
-      method: 'GET',
-      params: {
-        key: parameters.key,
-        username: parameters.username,
-        accountId: parameters.accountId,
-      },
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-
-  /**
-   * Adds a user as a watcher to a piece of content. Choose the user by doing one of the following:
-   *
-   * - Specify a user via a query parameter: Use the `accountId` to identify the user.
-   * - Do not specify a user: The currently logged-in user will be used.
-   *
-   * Note, you must add the `X-Atlassian-Token: no-check` header when making a request, as this operation has XSRF
-   * protection.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'Confluence Administrator' global permission
-   * if specifying a user, otherwise permission to access the Confluence site ('Can use' global permission).
-   */
-  async addContentWatcher(parameters: Parameters.AddContentWatcher, callback: Callback): Promise;
-  /**
-   * Adds a user as a watcher to a piece of content. Choose the user by doing one of the following:
-   *
-   * - Specify a user via a query parameter: Use the `accountId` to identify the user.
-   * - Do not specify a user: The currently logged-in user will be used.
-   *
-   * Note, you must add the `X-Atlassian-Token: no-check` header when making a request, as this operation has XSRF
-   * protection.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'Confluence Administrator' global permission
-   * if specifying a user, otherwise permission to access the Confluence site ('Can use' global permission).
-   */
-  async addContentWatcher(parameters: Parameters.AddContentWatcher, callback?: never): Promise;
-  async addContentWatcher(
-    parameters: Parameters.AddContentWatcher,
-    callback?: Callback,
-  ): Promise {
-    const config: RequestConfig = {
-      url: `/api/user/watch/content/${parameters.contentId}`,
-      method: 'POST',
-      params: {
-        key: parameters.key,
-        username: parameters.username,
-        accountId: parameters.accountId,
-      },
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-
-  /**
-   * Removes a user as a watcher from a piece of content. Choose the user by doing one of the following:
-   *
-   * - Specify a user via a query parameter: Use the `accountId` to identify the user.
-   * - Do not specify a user: The currently logged-in user will be used.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'Confluence Administrator' global permission
-   * if specifying a user, otherwise permission to access the Confluence site ('Can use' global permission).
-   */
-  async removeContentWatcher(
-    parameters: Parameters.RemoveContentWatcher,
-    callback: Callback,
-  ): Promise;
-  /**
-   * Removes a user as a watcher from a piece of content. Choose the user by doing one of the following:
-   *
-   * - Specify a user via a query parameter: Use the `accountId` to identify the user.
-   * - Do not specify a user: The currently logged-in user will be used.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'Confluence Administrator' global permission
-   * if specifying a user, otherwise permission to access the Confluence site ('Can use' global permission).
-   */
-  async removeContentWatcher(parameters: Parameters.RemoveContentWatcher, callback?: never): Promise;
-  async removeContentWatcher(
-    parameters: Parameters.RemoveContentWatcher,
-    callback?: Callback,
-  ): Promise {
-    const config: RequestConfig = {
-      url: `/api/user/watch/content/${parameters.contentId}`,
-      method: 'DELETE',
-      headers: {
-        'X-Atlassian-Token': parameters['X-Atlassian-Token'],
-      },
-      params: {
-        key: parameters.key,
-        username: parameters.username,
-        accountId: parameters.accountId,
-      },
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-
-  /**
-   * Returns whether a user is watching a label. Choose the user by doing one of the following:
-   *
-   * - Specify a user via a query parameter: Use the `accountId` to identify the user.
-   * - Do not specify a user: The currently logged-in user will be used.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'Confluence Administrator' global permission
-   * if specifying a user, otherwise permission to access the Confluence site ('Can use' global permission).
-   */
-  async isWatchingLabel(
-    parameters: Parameters.IsWatchingLabel,
-    callback: Callback,
-  ): Promise;
-  /**
-   * Returns whether a user is watching a label. Choose the user by doing one of the following:
-   *
-   * - Specify a user via a query parameter: Use the `accountId` to identify the user.
-   * - Do not specify a user: The currently logged-in user will be used.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'Confluence Administrator' global permission
-   * if specifying a user, otherwise permission to access the Confluence site ('Can use' global permission).
-   */
-  async isWatchingLabel(parameters: Parameters.IsWatchingLabel, callback?: never): Promise;
-  async isWatchingLabel(
-    parameters: Parameters.IsWatchingLabel,
-    callback?: Callback,
-  ): Promise {
-    const config: RequestConfig = {
-      url: `/api/user/watch/label/${parameters.labelName}`,
-      method: 'GET',
-      params: {
-        key: parameters.key,
-        username: parameters.username,
-        accountId: parameters.accountId,
-      },
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-
-  /**
-   * Adds a user as a watcher to a label. Choose the user by doing one of the following:
-   *
-   * - Specify a user via a query parameter: Use the `accountId` to identify the user.
-   * - Do not specify a user: The currently logged-in user will be used.
-   *
-   * Note, you must add the `X-Atlassian-Token: no-check` header when making a request, as this operation has XSRF
-   * protection.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'Confluence Administrator' global permission
-   * if specifying a user, otherwise permission to access the Confluence site ('Can use' global permission).
-   */
-  async addLabelWatcher(parameters: Parameters.AddLabelWatcher, callback: Callback): Promise;
-  /**
-   * Adds a user as a watcher to a label. Choose the user by doing one of the following:
-   *
-   * - Specify a user via a query parameter: Use the `accountId` to identify the user.
-   * - Do not specify a user: The currently logged-in user will be used.
-   *
-   * Note, you must add the `X-Atlassian-Token: no-check` header when making a request, as this operation has XSRF
-   * protection.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'Confluence Administrator' global permission
-   * if specifying a user, otherwise permission to access the Confluence site ('Can use' global permission).
-   */
-  async addLabelWatcher(parameters: Parameters.AddLabelWatcher, callback?: never): Promise;
-  async addLabelWatcher(parameters: Parameters.AddLabelWatcher, callback?: Callback): Promise {
-    const config: RequestConfig = {
-      url: `/api/user/watch/label/${parameters.labelName}`,
-      method: 'POST',
-      headers: {
-        'X-Atlassian-Token': parameters['X-Atlassian-Token'],
-      },
-      params: {
-        key: parameters.key,
-        username: parameters.username,
-        accountId: parameters.accountId,
-      },
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-
-  /**
-   * Removes a user as a watcher from a label. Choose the user by doing one of the following:
-   *
-   * - Specify a user via a query parameter: Use the `accountId` to identify the user.
-   * - Do not specify a user: The currently logged-in user will be used.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'Confluence Administrator' global permission
-   * if specifying a user, otherwise permission to access the Confluence site ('Can use' global permission).
-   */
-  async removeLabelWatcher(parameters: Parameters.RemoveLabelWatcher, callback: Callback): Promise;
-  /**
-   * Removes a user as a watcher from a label. Choose the user by doing one of the following:
-   *
-   * - Specify a user via a query parameter: Use the `accountId` to identify the user.
-   * - Do not specify a user: The currently logged-in user will be used.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'Confluence Administrator' global permission
-   * if specifying a user, otherwise permission to access the Confluence site ('Can use' global permission).
-   */
-  async removeLabelWatcher(parameters: Parameters.RemoveLabelWatcher, callback?: never): Promise;
-  async removeLabelWatcher(
-    parameters: Parameters.RemoveLabelWatcher,
-    callback?: Callback,
-  ): Promise {
-    const config: RequestConfig = {
-      url: `/api/user/watch/label/${parameters.labelName}`,
-      method: 'DELETE',
-      params: {
-        key: parameters.key,
-        username: parameters.username,
-        accountId: parameters.accountId,
-      },
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-
-  /**
-   * Returns whether a user is watching a space. Choose the user by doing one of the following:
-   *
-   * - Specify a user via a query parameter: Use the `accountId` to identify the user.
-   * - Do not specify a user: The currently logged-in user will be used.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'Confluence Administrator' global permission
-   * if specifying a user, otherwise permission to access the Confluence site ('Can use' global permission).
-   */
-  async isWatchingSpace(
-    parameters: Parameters.IsWatchingSpace,
-    callback: Callback,
-  ): Promise;
-  /**
-   * Returns whether a user is watching a space. Choose the user by doing one of the following:
-   *
-   * - Specify a user via a query parameter: Use the `accountId` to identify the user.
-   * - Do not specify a user: The currently logged-in user will be used.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'Confluence Administrator' global permission
-   * if specifying a user, otherwise permission to access the Confluence site ('Can use' global permission).
-   */
-  async isWatchingSpace(parameters: Parameters.IsWatchingSpace, callback?: never): Promise;
-  async isWatchingSpace(
-    parameters: Parameters.IsWatchingSpace,
-    callback?: Callback,
-  ): Promise {
-    const config: RequestConfig = {
-      url: `/api/user/watch/space/${parameters.spaceKey}`,
-      method: 'GET',
-      params: {
-        key: parameters.key,
-        username: parameters.username,
-        accountId: parameters.accountId,
-      },
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-
-  /**
-   * Adds a user as a watcher to a space. Choose the user by doing one of the following:
-   *
-   * - Specify a user via a query parameter: Use the `accountId` to identify the user.
-   * - Do not specify a user: The currently logged-in user will be used.
-   *
-   * Note, you must add the `X-Atlassian-Token: no-check` header when making a request, as this operation has XSRF
-   * protection.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'Confluence Administrator' global permission
-   * if specifying a user, otherwise permission to access the Confluence site ('Can use' global permission).
-   */
-  async addSpaceWatcher(parameters: Parameters.AddSpaceWatcher, callback: Callback): Promise;
-  /**
-   * Adds a user as a watcher to a space. Choose the user by doing one of the following:
-   *
-   * - Specify a user via a query parameter: Use the `accountId` to identify the user.
-   * - Do not specify a user: The currently logged-in user will be used.
-   *
-   * Note, you must add the `X-Atlassian-Token: no-check` header when making a request, as this operation has XSRF
-   * protection.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'Confluence Administrator' global permission
-   * if specifying a user, otherwise permission to access the Confluence site ('Can use' global permission).
-   */
-  async addSpaceWatcher(parameters: Parameters.AddSpaceWatcher, callback?: never): Promise;
-  async addSpaceWatcher(parameters: Parameters.AddSpaceWatcher, callback?: Callback): Promise {
-    const config: RequestConfig = {
-      url: `/api/user/watch/space/${parameters.spaceKey}`,
-      method: 'POST',
-      headers: {
-        'X-Atlassian-Token': parameters['X-Atlassian-Token'],
-      },
-      params: {
-        key: parameters.key,
-        username: parameters.username,
-        accountId: parameters.accountId,
-      },
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-
-  /**
-   * Removes a user as a watcher from a space. Choose the user by doing one of the following:
-   *
-   * - Specify a user via a query parameter: Use the `accountId` to identify the user.
-   * - Do not specify a user: The currently logged-in user will be used.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'Confluence Administrator' global permission
-   * if specifying a user, otherwise permission to access the Confluence site ('Can use' global permission).
-   */
-  async removeSpaceWatch(parameters: Parameters.RemoveSpaceWatch, callback: Callback): Promise;
-  /**
-   * Removes a user as a watcher from a space. Choose the user by doing one of the following:
-   *
-   * - Specify a user via a query parameter: Use the `accountId` to identify the user.
-   * - Do not specify a user: The currently logged-in user will be used.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'Confluence Administrator' global permission
-   * if specifying a user, otherwise permission to access the Confluence site ('Can use' global permission).
-   */
-  async removeSpaceWatch(parameters: Parameters.RemoveSpaceWatch, callback?: never): Promise;
-  async removeSpaceWatch(parameters: Parameters.RemoveSpaceWatch, callback?: Callback): Promise {
-    const config: RequestConfig = {
-      url: `/api/user/watch/space/${parameters.spaceKey}`,
-      method: 'DELETE',
-      params: {
-        key: parameters.key,
-        username: parameters.username,
-        accountId: parameters.accountId,
-      },
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-}
diff --git a/src/api/dynamicModules.ts b/src/api/dynamicModules.ts
deleted file mode 100644
index 63c1fe93..00000000
--- a/src/api/dynamicModules.ts
+++ /dev/null
@@ -1,83 +0,0 @@
-import type * as Parameters from './parameters';
-import type { Client } from '../clients';
-import type { Callback } from '../callback';
-import type { RequestConfig } from '../requestConfig';
-
-export class DynamicModules {
-  constructor(private client: Client) {}
-
-  /**
-   * Returns all modules registered dynamically by the calling app.
-   *
-   * **[Permissions](#permissions) required:** Only Connect apps can make this request.
-   */
-  async getModules(callback: Callback): Promise;
-  /**
-   * Returns all modules registered dynamically by the calling app.
-   *
-   * **[Permissions](#permissions) required:** Only Connect apps can make this request.
-   */
-  async getModules(callback?: never): Promise;
-  async getModules(callback?: Callback): Promise {
-    const config: RequestConfig = {
-      url: '/atlassian-connect/1/app/module/dynamic',
-      method: 'GET',
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-
-  /**
-   * Registers a list of modules. For the list of modules that support dynamic registration, see [Dynamic
-   * modules](https://developer.atlassian.com/cloud/confluence/dynamic-modules/).
-   *
-   * **[Permissions](#permissions) required:** Only Connect apps can make this request.
-   */
-  async registerModules(
-    parameters: Parameters.RegisterModules | undefined,
-    callback: Callback,
-  ): Promise;
-  /**
-   * Registers a list of modules. For the list of modules that support dynamic registration, see [Dynamic
-   * modules](https://developer.atlassian.com/cloud/confluence/dynamic-modules/).
-   *
-   * **[Permissions](#permissions) required:** Only Connect apps can make this request.
-   */
-  async registerModules(parameters?: Parameters.RegisterModules, callback?: never): Promise;
-  async registerModules(
-    parameters?: Parameters.RegisterModules,
-    callback?: Callback,
-  ): Promise {
-    const config: RequestConfig = {
-      url: '/atlassian-connect/1/app/module/dynamic',
-      method: 'POST',
-      data: parameters,
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-
-  /**
-   * Remove all or a list of modules registered by the calling app.
-   *
-   * **[Permissions](#permissions) required:** Only Connect apps can make this request.
-   */
-  async removeModules(parameters: Parameters.RemoveModules, callback: Callback): Promise;
-  /**
-   * Remove all or a list of modules registered by the calling app.
-   *
-   * **[Permissions](#permissions) required:** Only Connect apps can make this request.
-   */
-  async removeModules(parameters: Parameters.RemoveModules, callback?: never): Promise;
-  async removeModules(parameters: Parameters.RemoveModules, callback?: Callback): Promise {
-    const config: RequestConfig = {
-      url: '/atlassian-connect/1/app/module/dynamic',
-      method: 'DELETE',
-      params: {
-        moduleKey: parameters.moduleKey,
-      },
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-}
diff --git a/src/api/experimental.ts b/src/api/experimental.ts
deleted file mode 100644
index c9b26ec4..00000000
--- a/src/api/experimental.ts
+++ /dev/null
@@ -1,341 +0,0 @@
-import type * as Models from './models';
-import type * as Parameters from './parameters';
-import type { Client } from '../clients';
-import type { Callback } from '../callback';
-import type { RequestConfig } from '../requestConfig';
-
-export class Experimental {
-  constructor(private client: Client) {}
-
-  /**
-   * Moves a pagetree rooted at a page to the space's trash:
-   *
-   * - If the content's type is `page` and its status is `current`, it will be trashed including all its descendants.
-   * - For every other combination of content type and status, this API is not supported.
-   *
-   * This API accepts the pageTree delete request and returns a task ID. The delete process happens asynchronously.
-   *
-   * Use the `/longtask/` REST API to get the copy task status.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'Delete' permission for the space that the
-   * content is in.
-   */
-  async deletePageTree(
-    parameters: Parameters.DeletePageTree,
-    callback: Callback,
-  ): Promise;
-  /**
-   * Moves a pagetree rooted at a page to the space's trash:
-   *
-   * - If the content's type is `page` and its status is `current`, it will be trashed including all its descendants.
-   * - For every other combination of content type and status, this API is not supported.
-   *
-   * This API accepts the pageTree delete request and returns a task ID. The delete process happens asynchronously.
-   *
-   * Use the `/longtask/` REST API to get the copy task status.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'Delete' permission for the space that the
-   * content is in.
-   */
-  async deletePageTree(parameters: Parameters.DeletePageTree, callback?: never): Promise;
-  async deletePageTree(
-    parameters: Parameters.DeletePageTree,
-    callback?: Callback,
-  ): Promise {
-    const config: RequestConfig = {
-      url: `/api/content/${parameters.id}/pageTree`,
-      method: 'DELETE',
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-
-  /**
-   * Returns a list of labels associated with a space. Can provide a prefix as well as other filters to select different
-   * types of labels.
-   */
-  async getLabelsForSpace(
-    parameters: Parameters.GetLabelsForSpace,
-    callback: Callback,
-  ): Promise;
-  /**
-   * Returns a list of labels associated with a space. Can provide a prefix as well as other filters to select different
-   * types of labels.
-   */
-  async getLabelsForSpace(
-    parameters: Parameters.GetLabelsForSpace,
-    callback?: never,
-  ): Promise;
-  async getLabelsForSpace(
-    parameters: Parameters.GetLabelsForSpace,
-    callback?: Callback,
-  ): Promise {
-    const config: RequestConfig = {
-      url: `/api/space/${parameters.spaceKey}/label`,
-      method: 'GET',
-      params: {
-        prefix: parameters.prefix,
-        start: parameters.start,
-        limit: parameters.limit,
-      },
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-
-  /**
-   * Adds labels to a piece of content. Does not modify the existing labels.
-   *
-   * Notes:
-   *
-   * - Labels can also be added when creating content ([Create content](#api-content-post)).
-   * - Labels can be updated when updating content ([Update content](#api-content-id-put)). This will delete the existing
-   *   labels and replace them with the labels in the request.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to update the content.
-   */
-  async addLabelsToSpace(
-    parameters: Parameters.AddLabelsToSpace,
-    callback: Callback,
-  ): Promise;
-  /**
-   * Adds labels to a piece of content. Does not modify the existing labels.
-   *
-   * Notes:
-   *
-   * - Labels can also be added when creating content ([Create content](#api-content-post)).
-   * - Labels can be updated when updating content ([Update content](#api-content-id-put)). This will delete the existing
-   *   labels and replace them with the labels in the request.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to update the content.
-   */
-  async addLabelsToSpace(parameters: Parameters.AddLabelsToSpace, callback?: never): Promise;
-  async addLabelsToSpace(
-    parameters: Parameters.AddLabelsToSpace,
-    callback?: Callback,
-  ): Promise {
-    const config: RequestConfig = {
-      url: `/api/space/${parameters.spaceKey}/label`,
-      method: 'POST',
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-
-  async deleteLabelFromSpace(
-    parameters: Parameters.DeleteLabelFromSpace,
-    callback: Callback,
-  ): Promise;
-  async deleteLabelFromSpace(parameters: Parameters.DeleteLabelFromSpace, callback?: never): Promise;
-  async deleteLabelFromSpace(
-    parameters: Parameters.DeleteLabelFromSpace,
-    callback?: Callback,
-  ): Promise {
-    const config: RequestConfig = {
-      url: `/api/space/${parameters.spaceKey}/label`,
-      method: 'DELETE',
-      params: {
-        name: parameters.name,
-        prefix: parameters.prefix,
-      },
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-
-  /**
-   * Returns the properties for a user as list of property keys. For more information about user properties, see
-   * [Confluence entity properties](https://developer.atlassian.com/cloud/confluence/confluence-entity-properties/).
-   * `Note`, these properties stored against a user are on a Confluence site level and not space/content level.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to access the Confluence site
-   * ('Can use' global permission).
-   *
-   * @deprecated Will be removed in next major version. Use `userProperties.getUserProperties` instead.
-   */
-  async getUserProperties(
-    parameters: Parameters.GetUserProperties,
-    callback: Callback,
-  ): Promise;
-  /**
-   * Returns the properties for a user as list of property keys. For more information about user properties, see
-   * [Confluence entity properties](https://developer.atlassian.com/cloud/confluence/confluence-entity-properties/).
-   * `Note`, these properties stored against a user are on a Confluence site level and not space/content level.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to access the Confluence site
-   * ('Can use' global permission).
-   *
-   * @deprecated Will be removed in next major version. Use `userProperties.getUserProperties` instead.
-   */
-  async getUserProperties(
-    parameters: Parameters.GetUserProperties,
-    callback?: never,
-  ): Promise;
-  async getUserProperties(
-    parameters: Parameters.GetUserProperties,
-    callback?: Callback,
-  ): Promise {
-    const config: RequestConfig = {
-      url: `/api/user/${parameters.userId}/property`,
-      method: 'GET',
-      params: {
-        start: parameters.start,
-        limit: parameters.limit,
-      },
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-
-  /**
-   * Returns the property corresponding to `key` for a user. For more information about user properties, see [Confluence
-   * entity properties](https://developer.atlassian.com/cloud/confluence/confluence-entity-properties/). `Note`, these
-   * properties stored against a user are on a Confluence site level and not space/content level.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to access the Confluence site
-   * ('Can use' global permission).
-   *
-   * @deprecated Will be removed in next major version. Use `userProperties.getUserProperty` instead.
-   */
-  async getUserProperty(
-    parameters: Parameters.GetUserProperty,
-    callback: Callback,
-  ): Promise;
-  /**
-   * Returns the property corresponding to `key` for a user. For more information about user properties, see [Confluence
-   * entity properties](https://developer.atlassian.com/cloud/confluence/confluence-entity-properties/). `Note`, these
-   * properties stored against a user are on a Confluence site level and not space/content level.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to access the Confluence site
-   * ('Can use' global permission).
-   *
-   * @deprecated Will be removed in next major version. Use `userProperties.getUserProperty` instead.
-   */
-  async getUserProperty(parameters: Parameters.GetUserProperty, callback?: never): Promise;
-  async getUserProperty(
-    parameters: Parameters.GetUserProperty,
-    callback?: Callback,
-  ): Promise {
-    const config: RequestConfig = {
-      url: `/api/user/${parameters.userId}/property/${parameters.key}`,
-      method: 'GET',
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-
-  /**
-   * Creates a property for a user. For more information about user properties, see [Confluence entity properties]
-   * (https://developer.atlassian.com/cloud/confluence/confluence-entity-properties/). `Note`, these properties stored
-   * against a user are on a Confluence site level and not space/content level.
-   *
-   * `Note:` the number of properties which could be created per app in a tenant for each user might be restricted by
-   * fixed system limits. **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to access
-   * the Confluence site ('Can use' global permission).
-   *
-   * @deprecated Will be removed in next major version. Use `userProperties.createUserProperty` instead.
-   */
-  async createUserProperty(
-    parameters: Parameters.CreateUserProperty,
-    callback: Callback,
-  ): Promise;
-  /**
-   * Creates a property for a user. For more information about user properties, see [Confluence entity properties]
-   * (https://developer.atlassian.com/cloud/confluence/confluence-entity-properties/). `Note`, these properties stored
-   * against a user are on a Confluence site level and not space/content level.
-   *
-   * `Note:` the number of properties which could be created per app in a tenant for each user might be restricted by
-   * fixed system limits. **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to access
-   * the Confluence site ('Can use' global permission).
-   *
-   * @deprecated Will be removed in next major version. Use `userProperties.createUserProperty` instead.
-   */
-  async createUserProperty(parameters: Parameters.CreateUserProperty, callback?: never): Promise;
-  async createUserProperty(
-    parameters: Parameters.CreateUserProperty,
-    callback?: Callback,
-  ): Promise {
-    const config: RequestConfig = {
-      url: `/api/user/${parameters.userId}/property/${parameters.key}`,
-      method: 'POST',
-      data: {
-        value: parameters.value,
-      },
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-
-  /**
-   * Updates a property for the given user. Note, you cannot update the key of a user property, only the value. For more
-   * information about user properties, see [Confluence entity
-   * properties](https://developer.atlassian.com/cloud/confluence/confluence-entity-properties/). `Note`, these
-   * properties stored against a user are on a Confluence site level and not space/content level.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to access the Confluence site
-   * ('Can use' global permission).
-   *
-   * @deprecated Will be removed in next major version. Use `userProperties.updateUserProperty` instead.
-   */
-  async updateUserProperty(parameters: Parameters.UpdateUserProperty, callback: Callback): Promise;
-  /**
-   * Updates a property for the given user. Note, you cannot update the key of a user property, only the value. For more
-   * information about user properties, see [Confluence entity
-   * properties](https://developer.atlassian.com/cloud/confluence/confluence-entity-properties/). `Note`, these
-   * properties stored against a user are on a Confluence site level and not space/content level.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to access the Confluence site
-   * ('Can use' global permission).
-   *
-   * @deprecated Will be removed in next major version. Use `userProperties.updateUserProperty` instead.
-   */
-  async updateUserProperty(parameters: Parameters.UpdateUserProperty, callback?: never): Promise;
-  async updateUserProperty(
-    parameters: Parameters.UpdateUserProperty,
-    callback?: Callback,
-  ): Promise {
-    const config: RequestConfig = {
-      url: `/api/user/${parameters.userId}/property/${parameters.key}`,
-      method: 'PUT',
-      data: {
-        value: parameters.value,
-      },
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-
-  /**
-   * Deletes a property for the given user. For more information about user properties, see [Confluence entity
-   * properties](https://developer.atlassian.com/cloud/confluence/confluence-entity-properties/). `Note`, these
-   * properties stored against a user are on a Confluence site level and not space/content level.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to access the Confluence site
-   * ('Can use' global permission).
-   *
-   * @deprecated Will be removed in next major version. Use `userProperties.deleteUserProperty` instead.
-   */
-  async deleteUserProperty(parameters: Parameters.DeleteUserProperty, callback: Callback): Promise;
-  /**
-   * Deletes a property for the given user. For more information about user properties, see [Confluence entity
-   * properties](https://developer.atlassian.com/cloud/confluence/confluence-entity-properties/). `Note`, these
-   * properties stored against a user are on a Confluence site level and not space/content level.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to access the Confluence site
-   * ('Can use' global permission).
-   *
-   * @deprecated Will be removed in next major version. Use `userProperties.deleteUserProperty` instead.
-   */
-  async deleteUserProperty(parameters: Parameters.DeleteUserProperty, callback?: never): Promise;
-  async deleteUserProperty(
-    parameters: Parameters.DeleteUserProperty,
-    callback?: Callback,
-  ): Promise {
-    const config: RequestConfig = {
-      url: `/api/user/${parameters.userId}/property/${parameters.key}`,
-      method: 'DELETE',
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-}
diff --git a/src/api/group.ts b/src/api/group.ts
deleted file mode 100644
index dd43c205..00000000
--- a/src/api/group.ts
+++ /dev/null
@@ -1,505 +0,0 @@
-import type * as Models from './models';
-import type * as Parameters from './parameters';
-import type { Client } from '../clients';
-import type { Callback } from '../callback';
-import type { RequestConfig } from '../requestConfig';
-
-export class Group {
-  constructor(private client: Client) {}
-
-  /**
-   * Returns all user groups. The returned groups are ordered alphabetically in ascending order by group name.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to access the Confluence site
-   * ('Can use' global permission).
-   */
-  async getGroups(
-    parameters: Parameters.GetGroups | undefined,
-    callback: Callback,
-  ): Promise;
-  /**
-   * Returns all user groups. The returned groups are ordered alphabetically in ascending order by group name.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to access the Confluence site
-   * ('Can use' global permission).
-   */
-  async getGroups(parameters?: Parameters.GetGroups, callback?: never): Promise;
-  async getGroups(
-    parameters?: Parameters.GetGroups,
-    callback?: Callback,
-  ): Promise {
-    const config: RequestConfig = {
-      url: '/api/group',
-      method: 'GET',
-      params: {
-        start: parameters?.start,
-        limit: parameters?.limit,
-        accessType: parameters?.accessType,
-      },
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-
-  /**
-   * Creates a new user group.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: User must be a site admin.
-   */
-  async createGroup(
-    parameters: Parameters.CreateGroup | undefined,
-    callback: Callback,
-  ): Promise;
-  /**
-   * Creates a new user group.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: User must be a site admin.
-   */
-  async createGroup(parameters?: Parameters.CreateGroup, callback?: never): Promise;
-  async createGroup(parameters?: Parameters.CreateGroup, callback?: Callback): Promise {
-    const config: RequestConfig = {
-      url: '/api/group',
-      method: 'POST',
-      data: {
-        name: parameters?.name,
-      },
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-
-  /**
-   * Delete user group.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: User must be a site admin.
-   *
-   * @deprecated Will be removed in next major version.
-   */
-  async removeGroup(parameters: Parameters.RemoveGroup, callback: Callback): Promise;
-  /**
-   * Delete user group.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: User must be a site admin.
-   *
-   * @deprecated Will be removed in next major version.
-   */
-  async removeGroup(parameters: Parameters.RemoveGroup, callback?: never): Promise;
-  async removeGroup(parameters: Parameters.RemoveGroup, callback?: Callback): Promise {
-    const config: RequestConfig = {
-      url: '/api/group',
-      method: 'DELETE',
-      params: {
-        name: parameters.name,
-      },
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-
-  /**
-   * Returns a user group for a given group name.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to access the Confluence site
-   * ('Can use' global permission).
-   *
-   * @deprecated Will be removed in next major version.
-   */
-  async getGroupByQueryParam(
-    parameters: Parameters.GetGroupByQueryParam,
-    callback: Callback,
-  ): Promise;
-  /**
-   * Returns a user group for a given group name.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to access the Confluence site
-   * ('Can use' global permission).
-   *
-   * @deprecated Will be removed in next major version.
-   */
-  async getGroupByQueryParam(
-    parameters: Parameters.GetGroupByQueryParam,
-    callback?: never,
-  ): Promise;
-  async getGroupByQueryParam(
-    parameters: Parameters.GetGroupByQueryParam,
-    callback?: Callback,
-  ): Promise {
-    const config: RequestConfig = {
-      url: '/api/group/by-name',
-      method: 'GET',
-      params: {
-        name: parameters.name,
-      },
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-
-  /**
-   * Returns a user group for a given group id.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to access the Confluence site
-   * ('Can use' global permission).
-   */
-  async getGroupByGroupId(
-    parameters: Parameters.GetGroupByGroupId,
-    callback: Callback,
-  ): Promise;
-  /**
-   * Returns a user group for a given group id.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to access the Confluence site
-   * ('Can use' global permission).
-   */
-  async getGroupByGroupId(parameters: Parameters.GetGroupByGroupId, callback?: never): Promise;
-  async getGroupByGroupId(
-    parameters: Parameters.GetGroupByGroupId,
-    callback?: Callback,
-  ): Promise {
-    const config: RequestConfig = {
-      url: '/api/group/by-id',
-      method: 'GET',
-      params: {
-        id: parameters.id,
-      },
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-
-  /**
-   * Delete user group.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: User must be a site admin.
-   */
-  async removeGroupById(parameters: Parameters.DeleteGroupById, callback: Callback): Promise;
-  /**
-   * Delete user group.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: User must be a site admin.
-   */
-  async removeGroupById(parameters: Parameters.DeleteGroupById, callback?: never): Promise;
-  async removeGroupById(parameters: Parameters.DeleteGroupById, callback?: Callback): Promise {
-    const config: RequestConfig = {
-      url: '/api/group/by-id',
-      method: 'DELETE',
-      params: {
-        id: parameters.id,
-      },
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-
-  /**
-   * Returns a user group for a given group name.
-   *
-   * Use updated Get group API
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to access the Confluence site
-   * ('Can use' global permission).
-   *
-   * @deprecated Will be removed in next major version.
-   */
-  async getGroupByName(parameters: Parameters.GetGroupByName, callback: Callback): Promise;
-  /**
-   * Returns a user group for a given group name.
-   *
-   * Use updated Get group API
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to access the Confluence site
-   * ('Can use' global permission).
-   *
-   * @deprecated Will be removed in next major version.
-   */
-  async getGroupByName(parameters: Parameters.GetGroupByName, callback?: never): Promise;
-  async getGroupByName(
-    parameters: Parameters.GetGroupByName,
-    callback?: Callback,
-  ): Promise {
-    const config: RequestConfig = {
-      url: `/api/group/${parameters.groupName}`,
-      method: 'GET',
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-
-  /**
-   * Returns the users that are members of a group.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to access the Confluence site
-   * ('Can use' global permission).
-   *
-   * @deprecated Will be removed in next major version.
-   */
-  async getMembersByQueryParam(
-    parameters: Parameters.GetMembersByQueryParam,
-    callback: Callback,
-  ): Promise;
-  /**
-   * Returns the users that are members of a group.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to access the Confluence site
-   * ('Can use' global permission).
-   *
-   * @deprecated Will be removed in next major version.
-   */
-  async getMembersByQueryParam(
-    parameters: Parameters.GetMembersByQueryParam,
-    callback?: never,
-  ): Promise;
-  async getMembersByQueryParam(
-    parameters: Parameters.GetMembersByQueryParam,
-    callback?: Callback,
-  ): Promise {
-    const config: RequestConfig = {
-      url: '/api/group/member',
-      method: 'GET',
-      params: {
-        name: parameters.name,
-        start: parameters.start,
-        limit: parameters.limit,
-        shouldReturnTotalSize: parameters.shouldReturnTotalSize,
-      },
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-
-  /** Get search results of groups by partial query provided. */
-  async searchGroups(
-    parameters: Parameters.SearchGroups,
-    callback: Callback,
-  ): Promise;
-  /** Get search results of groups by partial query provided. */
-  async searchGroups(parameters: Parameters.SearchGroups, callback?: never): Promise;
-  async searchGroups(
-    parameters: Parameters.SearchGroups,
-    callback?: Callback,
-  ): Promise {
-    const config: RequestConfig = {
-      url: '/api/group/picker',
-      method: 'GET',
-      params: {
-        query: parameters.query,
-        start: parameters.start,
-        limit: parameters.limit,
-        shouldReturnTotalSize: parameters.shouldReturnTotalSize,
-      },
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-
-  /**
-   * Returns the users that are members of a group.
-   *
-   * Use updated Get group API
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to access the Confluence site
-   * ('Can use' global permission).
-   */
-  async getGroupMembersByGroupId(
-    parameters: Parameters.GetGroupMembersByGroupId,
-    callback: Callback,
-  ): Promise;
-  /**
-   * Returns the users that are members of a group.
-   *
-   * Use updated Get group API
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to access the Confluence site
-   * ('Can use' global permission).
-   */
-  async getGroupMembersByGroupId(
-    parameters: Parameters.GetGroupMembersByGroupId,
-    callback?: never,
-  ): Promise;
-  async getGroupMembersByGroupId(
-    parameters: Parameters.GetGroupMembersByGroupId,
-    callback?: Callback,
-  ): Promise {
-    const config: RequestConfig = {
-      url: `/api/group/${parameters.groupId}/membersByGroupId`,
-      method: 'GET',
-      params: {
-        start: parameters.start,
-        limit: parameters.limit,
-        shouldReturnTotalSize: parameters.shouldReturnTotalSize,
-        expand: parameters.expand,
-      },
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-
-  /**
-   * Adds a user as a member in a group represented by its groupId
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: User must be a site admin.
-   */
-  async addUserToGroupByGroupId(
-    parameters: Parameters.AddUserToGroupByGroupId,
-    callback: Callback,
-  ): Promise;
-  /**
-   * Adds a user as a member in a group represented by its groupId
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: User must be a site admin.
-   */
-  async addUserToGroupByGroupId(
-    parameters: Parameters.AddUserToGroupByGroupId,
-    callback?: never,
-  ): Promise;
-  async addUserToGroupByGroupId(
-    parameters: Parameters.AddUserToGroupByGroupId,
-    callback?: Callback,
-  ): Promise {
-    const config: RequestConfig = {
-      url: '/api/group/userByGroupId',
-      method: 'POST',
-      params: {
-        groupId: parameters.groupId,
-      },
-      data: {
-        accountId: parameters.accountId,
-      },
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-
-  /**
-   * Remove user as a member from a group.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: User must be a site admin.
-   */
-  async removeMemberFromGroupByGroupId(
-    parameters: Parameters.RemoveMemberFromGroupByGroupId,
-    callback: Callback,
-  ): Promise;
-  /**
-   * Remove user as a member from a group.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: User must be a site admin.
-   */
-  async removeMemberFromGroupByGroupId(
-    parameters: Parameters.RemoveMemberFromGroupByGroupId,
-    callback?: never,
-  ): Promise;
-  async removeMemberFromGroupByGroupId(
-    parameters: Parameters.RemoveMemberFromGroupByGroupId,
-    callback?: Callback,
-  ): Promise {
-    const config: RequestConfig = {
-      url: '/api/group/userByGroupId',
-      method: 'DELETE',
-      params: {
-        groupId: parameters.groupId,
-        accountId: parameters.accountId,
-      },
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-
-  /**
-   * Adds a user as a member in a group.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: User must be a site admin.
-   */
-  async addUserToGroup(parameters: Parameters.AddUserToGroup, callback: Callback): Promise;
-  /**
-   * Adds a user as a member in a group.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: User must be a site admin.
-   */
-  async addUserToGroup(parameters: Parameters.AddUserToGroup, callback?: never): Promise;
-  async addUserToGroup(parameters: Parameters.AddUserToGroup, callback?: Callback): Promise {
-    const config: RequestConfig = {
-      url: '/api/group/user',
-      method: 'POST',
-      params: {
-        name: parameters.name,
-      },
-      data: {
-        accountId: parameters.accountId,
-      },
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-
-  /**
-   * Remove user as a member from a group.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: User must be a site admin.
-   */
-  async removeMemberFromGroup(
-    parameters: Parameters.RemoveMemberFromGroup,
-    callback: Callback,
-  ): Promise;
-  /**
-   * Remove user as a member from a group.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: User must be a site admin.
-   */
-  async removeMemberFromGroup(parameters: Parameters.RemoveMemberFromGroup, callback?: never): Promise;
-  async removeMemberFromGroup(
-    parameters: Parameters.RemoveMemberFromGroup,
-    callback?: Callback,
-  ): Promise {
-    const config: RequestConfig = {
-      url: '/api/group/user',
-      method: 'DELETE',
-      params: {
-        name: parameters.name,
-        accountId: parameters.accountId,
-      },
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-
-  /**
-   * Returns the users that are members of a group.
-   *
-   * Use updated Get group API
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to access the Confluence site
-   * ('Can use' global permission).
-   *
-   * @deprecated Will be removed in next major version. Use `group.getGroupMembersByGroupId`
-   */
-  async getGroupMembers(
-    parameters: Parameters.GetGroupMembers,
-    callback: Callback,
-  ): Promise;
-  /**
-   * Returns the users that are members of a group.
-   *
-   * Use updated Get group API
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to access the Confluence site
-   * ('Can use' global permission).
-   *
-   * @deprecated Will be removed in next major version. Use `group.getGroupMembersByGroupId`
-   */
-  async getGroupMembers(parameters: Parameters.GetGroupMembers, callback?: never): Promise;
-  async getGroupMembers(
-    parameters: Parameters.GetGroupMembers,
-    callback?: Callback,
-  ): Promise {
-    const config: RequestConfig = {
-      url: `/api/group/${parameters.groupName}/member`,
-      method: 'GET',
-      params: {
-        start: parameters.start,
-        limit: parameters.limit,
-      },
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-}
diff --git a/src/api/index.ts b/src/api/index.ts
deleted file mode 100644
index f3241061..00000000
--- a/src/api/index.ts
+++ /dev/null
@@ -1,32 +0,0 @@
-export * from './analytics';
-export * from './audit';
-export * from './content';
-export * from './contentAttachments';
-export * from './contentBody';
-export * from './contentChildrenAndDescendants';
-export * from './contentComments';
-export * from './contentLabels';
-export * from './contentMacroBody';
-export * from './contentPermissions';
-export * from './contentProperties';
-export * from './contentRestrictions';
-export * from './contentStates';
-export * from './contentVersions';
-export * from './contentWatches';
-export * from './dynamicModules';
-export * from './experimental';
-export * from './group';
-export * from './inlineTasks';
-export * from './labelInfo';
-export * from './longRunningTask';
-export * from './relation';
-export * from './search';
-export * from './settings';
-export * from './space';
-export * from './spacePermissions';
-export * from './spaceProperties';
-export * from './spaceSettings';
-export * from './template';
-export * from './themes';
-export * from './users';
-export * from './userProperties';
diff --git a/src/api/inlineTasks.ts b/src/api/inlineTasks.ts
deleted file mode 100644
index 599699c0..00000000
--- a/src/api/inlineTasks.ts
+++ /dev/null
@@ -1,119 +0,0 @@
-import type * as Models from './models';
-import type * as Parameters from './parameters';
-import type { Callback } from '../callback';
-import type { Client } from '../clients';
-import type { RequestConfig } from '../requestConfig';
-
-/** @deprecated Will be removed in next major version. */
-export class InlineTasks {
-  constructor(private client: Client) {}
-
-  /**
-   * Returns inline tasks based on the search query.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to access the Confluence site
-   * ('Can use' global permission). Only tasks in contents that the user has permission to view are returned.
-   *
-   * @deprecated Will be removed in next major version.
-   */
-  async searchTasks(
-    parameters: Parameters.SearchTasks | undefined,
-    callback: Callback,
-  ): Promise;
-  /**
-   * Returns inline tasks based on the search query.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to access the Confluence site
-   * ('Can use' global permission). Only tasks in contents that the user has permission to view are returned.
-   *
-   * @deprecated Will be removed in next major version.
-   */
-  async searchTasks(parameters?: Parameters.SearchTasks, callback?: never): Promise;
-  async searchTasks(
-    parameters?: Parameters.SearchTasks,
-    callback?: Callback,
-  ): Promise {
-    const config: RequestConfig = {
-      url: '/api/inlinetasks/search',
-      method: 'GET',
-      params: {
-        start: parameters?.start,
-        limit: parameters?.limit,
-        spaceKey: parameters?.spaceKey,
-        pageId: parameters?.pageId,
-        assignee: parameters?.assignee,
-        creator: parameters?.creator,
-        completedUser: parameters?.completedUser,
-        duedateFrom: parameters?.duedateFrom,
-        duedateTo: parameters?.duedateTo,
-        createdateFrom: parameters?.createdateFrom,
-        createdateTo: parameters?.createdateTo,
-        completedateFrom: parameters?.completedateFrom,
-        completedateTo: parameters?.completedateTo,
-        status: parameters?.status,
-      },
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-
-  /**
-   * Returns inline task based on the global ID.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to view the content associated
-   * with the task.
-   *
-   * @deprecated Will be removed in next major version.
-   */
-  async getTaskById(parameters: Parameters.GetTaskById, callback: Callback): Promise;
-  /**
-   * Returns inline task based on the global ID.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to view the content associated
-   * with the task.
-   *
-   * @deprecated Will be removed in next major version.
-   */
-  async getTaskById(parameters: Parameters.GetTaskById, callback?: never): Promise;
-  async getTaskById(parameters: Parameters.GetTaskById, callback?: Callback): Promise {
-    const config: RequestConfig = {
-      url: `/api/inlinetasks/${parameters.inlineTaskId}`,
-      method: 'GET',
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-
-  /**
-   * Updates an inline tasks status given its global ID
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to update the content associated
-   * with the task.
-   *
-   * @deprecated Will be removed in next major version.
-   */
-  async updateTaskById(parameters: Parameters.UpdateTaskById, callback: Callback): Promise;
-  /**
-   * Updates an inline tasks status given its global ID
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to update the content associated
-   * with the task.
-   *
-   * @deprecated Will be removed in next major version.
-   */
-  async updateTaskById(parameters: Parameters.UpdateTaskById, callback?: never): Promise;
-  async updateTaskById(
-    parameters: Parameters.UpdateTaskById,
-    callback?: Callback,
-  ): Promise {
-    const config: RequestConfig = {
-      url: `/api/inlinetasks/${parameters.inlineTaskId}`,
-      method: 'PUT',
-      data: {
-        status: parameters.status,
-      },
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-}
diff --git a/src/api/labelInfo.ts b/src/api/labelInfo.ts
deleted file mode 100644
index 72fc39e6..00000000
--- a/src/api/labelInfo.ts
+++ /dev/null
@@ -1,47 +0,0 @@
-import type * as Models from './models';
-import type * as Parameters from './parameters';
-import type { Client } from '../clients';
-import type { Callback } from '../callback';
-import type { RequestConfig } from '../requestConfig';
-
-export class LabelInfo {
-  constructor(private client: Client) {}
-
-  /**
-   * Returns label information and a list of contents associated with the label.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to access the Confluence site
-   * ('Can use' global permission). Only contents that the user is permitted to view is returned.
-   */
-  async getAllLabelContent(
-    parameters: Parameters.GetAllLabelContent,
-    callback: Callback,
-  ): Promise;
-  /**
-   * Returns label information and a list of contents associated with the label.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to access the Confluence site
-   * ('Can use' global permission). Only contents that the user is permitted to view is returned.
-   */
-  async getAllLabelContent(
-    parameters: Parameters.GetAllLabelContent,
-    callback?: never,
-  ): Promise;
-  async getAllLabelContent(
-    parameters: Parameters.GetAllLabelContent,
-    callback?: Callback,
-  ): Promise {
-    const config: RequestConfig = {
-      url: '/api/label',
-      method: 'GET',
-      params: {
-        name: parameters.name,
-        type: parameters.type,
-        start: parameters.start,
-        limit: parameters.limit,
-      },
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-}
diff --git a/src/api/longRunningTask.ts b/src/api/longRunningTask.ts
deleted file mode 100644
index f2a7e0b1..00000000
--- a/src/api/longRunningTask.ts
+++ /dev/null
@@ -1,76 +0,0 @@
-import type * as Models from './models';
-import type * as Parameters from './parameters';
-import type { Client } from '../clients';
-import type { Callback } from '../callback';
-import type { RequestConfig } from '../requestConfig';
-
-export class LongRunningTask {
-  constructor(private client: Client) {}
-
-  /**
-   * Returns information about all active long-running tasks (e.g. space export), such as how long each task has been
-   * running and the percentage of each task that has completed.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to access the Confluence site
-   * ('Can use' global permission).
-   */
-  async getTasks(
-    parameters: Parameters.GetTasks | undefined,
-    callback: Callback,
-  ): Promise;
-  /**
-   * Returns information about all active long-running tasks (e.g. space export), such as how long each task has been
-   * running and the percentage of each task that has completed.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to access the Confluence site
-   * ('Can use' global permission).
-   */
-  async getTasks(parameters?: Parameters.GetTasks, callback?: never): Promise;
-  async getTasks(
-    parameters?: Parameters.GetTasks,
-    callback?: Callback,
-  ): Promise {
-    const config: RequestConfig = {
-      url: '/api/longtask',
-      method: 'GET',
-      params: {
-        key: parameters?.key,
-        start: parameters?.start,
-        limit: parameters?.limit,
-      },
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-
-  /**
-   * Returns information about an active long-running task (e.g. space export), such as how long it has been running and
-   * the percentage of the task that has completed.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to access the Confluence site
-   * ('Can use' global permission).
-   */
-  async getTask(
-    parameters: Parameters.GetTask,
-    callback: Callback,
-  ): Promise;
-  /**
-   * Returns information about an active long-running task (e.g. space export), such as how long it has been running and
-   * the percentage of the task that has completed.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to access the Confluence site
-   * ('Can use' global permission).
-   */
-  async getTask(parameters: Parameters.GetTask, callback?: never): Promise;
-  async getTask(
-    parameters: Parameters.GetTask,
-    callback?: Callback,
-  ): Promise {
-    const config: RequestConfig = {
-      url: `/api/longtask/${parameters.id}`,
-      method: 'GET',
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-}
diff --git a/src/api/models/accountId.ts b/src/api/models/accountId.ts
deleted file mode 100644
index 4f99f9f3..00000000
--- a/src/api/models/accountId.ts
+++ /dev/null
@@ -1,3 +0,0 @@
-export interface AccountId {
-  accountId: string;
-}
diff --git a/src/api/models/accountIdEmailRecord.ts b/src/api/models/accountIdEmailRecord.ts
deleted file mode 100644
index b86dfeb7..00000000
--- a/src/api/models/accountIdEmailRecord.ts
+++ /dev/null
@@ -1,4 +0,0 @@
-export interface AccountIdEmailRecord {
-  accountId: string;
-  email: string;
-}
diff --git a/src/api/models/accountIdEmailRecordArray.ts b/src/api/models/accountIdEmailRecordArray.ts
deleted file mode 100644
index 3253ba21..00000000
--- a/src/api/models/accountIdEmailRecordArray.ts
+++ /dev/null
@@ -1,3 +0,0 @@
-import type { AccountIdEmailRecord } from './accountIdEmailRecord';
-
-export type AccountIdEmailRecordArray = AccountIdEmailRecord[];
diff --git a/src/api/models/addContentRestriction.ts b/src/api/models/addContentRestriction.ts
deleted file mode 100644
index 297f78e7..00000000
--- a/src/api/models/addContentRestriction.ts
+++ /dev/null
@@ -1,45 +0,0 @@
-export interface AddContentRestriction {
-  /** The restriction operation applied to content. */
-  operation: string;
-  /**
-   * The users/groups that the restrictions will be applied to. At least one of `user` or `group` must be specified for
-   * this object.
-   */
-  restrictions: {
-    /**
-     * The users that the restrictions will be applied to. This array must have at least one item, otherwise it should
-     * be omitted.
-     */
-    user?: {
-      /** Set to 'known'. */
-      type: string;
-      /**
-       * This property is no longer available and will be removed from the documentation soon. Use `accountId` instead.
-       * See the [deprecation notice](/cloud/confluence/deprecation-notice-user-privacy-api-migration-guide/) for
-       * details.
-       */
-      username?: string;
-      /**
-       * This property is no longer available and will be removed from the documentation soon. Use `accountId` instead.
-       * See the [deprecation notice](/cloud/confluence/deprecation-notice-user-privacy-api-migration-guide/) for
-       * details.
-       */
-      userKey?: string;
-      /**
-       * The account ID of the user, which uniquely identifies the user across all Atlassian products. For example,
-       * `384093:32b4d9w0-f6a5-3535-11a3-9c8c88d10192`.
-       */
-      accountId: string;
-    }[];
-    /**
-     * The groups that the restrictions will be applied to. This array must have at least one item, otherwise it should
-     * be omitted.
-     */
-    group?: {
-      /** Set to 'group'. */
-      type: string;
-      /** The name of the group. */
-      name: string;
-    }[];
-  };
-}
diff --git a/src/api/models/addContentRestrictionUpdateArray.ts b/src/api/models/addContentRestrictionUpdateArray.ts
deleted file mode 100644
index 84d54eec..00000000
--- a/src/api/models/addContentRestrictionUpdateArray.ts
+++ /dev/null
@@ -1,3 +0,0 @@
-import type { AddContentRestriction } from './addContentRestriction';
-
-export type AddContentRestrictionUpdateArray = AddContentRestriction[];
diff --git a/src/api/models/affectedObject.ts b/src/api/models/affectedObject.ts
deleted file mode 100644
index 3c4cef10..00000000
--- a/src/api/models/affectedObject.ts
+++ /dev/null
@@ -1,4 +0,0 @@
-export interface AffectedObject {
-  name: string;
-  objectType: string;
-}
diff --git a/src/api/models/appDescriptor.ts b/src/api/models/appDescriptor.ts
deleted file mode 100644
index b673672c..00000000
--- a/src/api/models/appDescriptor.ts
+++ /dev/null
@@ -1,87 +0,0 @@
-/* eslint-disable @typescript-eslint/no-explicit-any */
-import type { Lifecycle } from './lifecycle';
-
-export interface AppDescriptor {
-  /** Defines the authentication type to use when signing requests between the host application and the connect app. */
-  authentication: {
-    /** The type of authentication to use. */
-    type: 'jwt' | 'JWT' | 'none' | 'NONE';
-  };
-
-  /**
-   * The base url of the remote app, which is used for all communications back to the app instance.
-   *
-   * The baseUrl must start with `https://` to ensure that all data is sent securely between our cloud instances and
-   * your app.
-   *
-   * Note: each app must have a unique baseUrl. If you would like to serve multiple apps from the same host, consider
-   * adding a path prefix into the baseUrl.
-   */
-  baseUrl: string;
-
-  /** A unique key to identify the app. This key must be <= 64 characters. */
-  key: string;
-
-  /**
-   * The API version is an OPTIONAL integer. If omitted we will infer an API version of 1.
-   *
-   * The intention behind the API version is to allow vendors the ability to beta test a major revision to their Connect
-   * app as a private version, and have a seamless transition for those beta customers (and existing customers) once the
-   * major revision is launched.
-   *
-   * Vendors can accomplish this by listing a new private version of their app, with a new descriptor hosted at a new
-   * URL.
-   *
-   * They use the Atlassian Marketplace's access token facilities to share this version with customers (or for internal
-   * use). When this version is ready to be taken live, it can be transitioned from private to public, and all customers
-   * will be seamlessly updated.
-   *
-   * It's important to note that this approach allows vendors to create new versions manually, despite the fact that in
-   * the common case, the versions are automatically created. This has a few benefits-- for example, it gives vendors
-   * the ability to change their descriptor URL if they need to (the descriptor URL will be immutable for existing
-   * versions).
-   */
-  apiVersion?: number;
-
-  /**
-   * A human readable description of what the app does. The description will be visible in the **Manage Apps** section
-   * of the administration console. Provide meaningful and identifying information for the instance administrator.
-   */
-  description?: string;
-
-  /**
-   * Whether or not to enable licensing options in the UPM/Marketplace for this app.
-   *
-   * @default false
-   */
-  enableLicensing?: boolean;
-
-  /** Allows the app to register for app lifecycle notifications. */
-  lifecycle?: Lifecycle;
-
-  /** A set of links that the app wishes to publish. */
-  links?: Record;
-
-  /** The list of modules this app provides. */
-  modules?: Record;
-
-  /**
-   * The human-readable name of the app. The app's name is visible to customers and must therefore be consistent with
-   * the name used to distribute the app such as any listing in the [Atlassian
-   * Marketplace](https://marketplace.atlassian.com/). Immutable records are created during the first installation of an
-   * app, one of which includes the name of the app. It is therefore important that the name of the app is correct as it
-   * can not be changed.
-   */
-  name?: string;
-
-  /** Set of [scopes](https://developer.atlassian.com/cloud/jira/platform/scopes/) requested by this app. */
-  scopes?: string[];
-
-  /** The vendor who is offering the app. */
-  vendor?: {
-    /** The name of the app vendor. Supply your name or the name of the company you work for. */
-    name: string;
-    /** The URL for the vendor's website. */
-    url: string;
-  };
-}
diff --git a/src/api/models/asyncContentBody.ts b/src/api/models/asyncContentBody.ts
deleted file mode 100644
index c55b8895..00000000
--- a/src/api/models/asyncContentBody.ts
+++ /dev/null
@@ -1,31 +0,0 @@
-import type { EmbeddedContent } from './embeddedContent';
-import type { GenericLinks } from './genericLinks';
-import type { WebResourceDependencies } from './webResourceDependencies';
-
-export interface AsyncContentBody {
-  value?: string;
-  representation?: string;
-  renderTaskId?: string;
-  error?: string;
-  /**
-   * Rerunning is reserved for when the job is working, but there is a previous run's value in the cache. You may choose
-   * to continue polling, or use the cached value.
-   */
-  status?: string;
-  embeddedContent?: EmbeddedContent[];
-  webresource?: WebResourceDependencies;
-  mediaToken?: {
-    collectionIds?: string[];
-    contentId?: string;
-    expiryDateTime?: string;
-    fileIds?: string[];
-    token?: string;
-  };
-  Expandable?: {
-    content?: string;
-    embeddedContent?: string;
-    webresource?: string;
-    mediaToken?: string;
-  };
-  Links?: GenericLinks;
-}
diff --git a/src/api/models/asyncId.ts b/src/api/models/asyncId.ts
deleted file mode 100644
index 60614e4e..00000000
--- a/src/api/models/asyncId.ts
+++ /dev/null
@@ -1,3 +0,0 @@
-export interface AsyncId {
-  asyncId: string;
-}
diff --git a/src/api/models/attachment.ts b/src/api/models/attachment.ts
deleted file mode 100644
index fc2ecc6d..00000000
--- a/src/api/models/attachment.ts
+++ /dev/null
@@ -1,33 +0,0 @@
-/* eslint-disable @typescript-eslint/no-explicit-any */
-import type { AttachmentMetadata } from './attachmentMetadata';
-import type { GenericLinks } from './genericLinks';
-
-export interface Attachment {
-  id: string;
-  type: 'attachment' | string;
-  status: 'current' | string;
-  title: string;
-  macroRenderedOutput: any;
-  metadata: AttachmentMetadata;
-  extensions: {
-    mediaType: string;
-    fileSize: number;
-    comment: string;
-    mediaTypeDescription: string;
-    fileId: string;
-    collectionName?: string;
-  };
-  _expandable: {
-    childTypes: string;
-    operations: string;
-    schedulePublishDate: string;
-    children: string;
-    restrictions: string;
-    history: string;
-    ancestors: string;
-    body: string;
-    descendants: string;
-    space: string;
-  };
-  _links: GenericLinks;
-}
diff --git a/src/api/models/attachmentContainer.ts b/src/api/models/attachmentContainer.ts
deleted file mode 100644
index e069208c..00000000
--- a/src/api/models/attachmentContainer.ts
+++ /dev/null
@@ -1,29 +0,0 @@
-/* eslint-disable @typescript-eslint/no-explicit-any */
-import type { GenericLinks } from './genericLinks';
-
-export interface AttachmentContainer {
-  id: string;
-  type: 'page' | 'string';
-  status: 'current' | string;
-  title: string;
-  macroRenderedOutput: any;
-  extensions: {
-    position: number;
-  };
-  _expandable: {
-    container: string;
-    metadata: string;
-    restrictions: string;
-    history: string;
-    body: string;
-    version: string;
-    descendants: string;
-    space: string;
-    childTypes: string;
-    operations: string;
-    schedulePublishDate: string;
-    children: string;
-    ancestors: string;
-  };
-  _links: GenericLinks;
-}
diff --git a/src/api/models/attachmentMetadata.ts b/src/api/models/attachmentMetadata.ts
deleted file mode 100644
index b3c20d90..00000000
--- a/src/api/models/attachmentMetadata.ts
+++ /dev/null
@@ -1,21 +0,0 @@
-import type { GenericLinks } from './genericLinks';
-
-export interface AttachmentMetadata {
-  comment: string;
-  mediaType: string;
-  labels: {
-    results: string[];
-    start: number;
-    limit: number;
-    size: number;
-    _links: GenericLinks;
-  };
-  _expandable: {
-    currentuser: string;
-    comments: string;
-    simple: string;
-    properties: string;
-    frontend: string;
-    likes: string;
-  };
-}
diff --git a/src/api/models/auditRecord.ts b/src/api/models/auditRecord.ts
deleted file mode 100644
index 54198231..00000000
--- a/src/api/models/auditRecord.ts
+++ /dev/null
@@ -1,20 +0,0 @@
-import type { AffectedObject } from './affectedObject';
-import type { ChangedValue } from './changedValue';
-
-export interface AuditRecord {
-  author: {
-    type: string;
-    displayName: string;
-    operations: {};
-  };
-  remoteAddress: string;
-  /** The creation date-time of the audit record, as a timestamp. */
-  creationDate: number;
-  summary: string;
-  description: string;
-  category: string;
-  sysAdmin: boolean;
-  affectedObject: AffectedObject;
-  changedValues: ChangedValue[];
-  associatedObjects: AffectedObject[];
-}
diff --git a/src/api/models/auditRecordArray.ts b/src/api/models/auditRecordArray.ts
deleted file mode 100644
index 758eb1e8..00000000
--- a/src/api/models/auditRecordArray.ts
+++ /dev/null
@@ -1,10 +0,0 @@
-import type { AuditRecord } from './auditRecord';
-import type { GenericLinks } from './genericLinks';
-
-export interface AuditRecordArray {
-  results: AuditRecord[];
-  start: number;
-  limit: number;
-  size: number;
-  _links: GenericLinks;
-}
diff --git a/src/api/models/auditRecordCreate.ts b/src/api/models/auditRecordCreate.ts
deleted file mode 100644
index 907c99a0..00000000
--- a/src/api/models/auditRecordCreate.ts
+++ /dev/null
@@ -1,44 +0,0 @@
-import type { AffectedObject } from './affectedObject';
-import type { ChangedValue } from './changedValue';
-
-export interface AuditRecordCreate {
-  /**
-   * The user that actioned the event. If `author` is not specified, then all `author` properties will be set to
-   * null/empty, except for `type` which will be set to 'user'.
-   */
-  author?: {
-    /** Set to 'user'. */
-    type: string;
-    /** The name that is displayed on the audit log in the Confluence UI. */
-    displayName?: string;
-    /** Always defaults to null. */
-    operations?: {};
-  };
-  /** The IP address of the computer where the event was initiated from. */
-  remoteAddress: string;
-  /**
-   * The creation date-time of the audit record, as a timestamp. This is converted to a date-time display in the
-   * Confluence UI. If the `creationDate` is not specified, then it will be set to the timestamp for the current
-   * date-time.
-   */
-  creationDate?: number;
-  /** The summary of the event, which is displayed in the 'Change' column on the audit log in the Confluence UI. */
-  summary?: string;
-  /**
-   * A long description of the event, which is displayed in the 'Description' field on the audit log in the Confluence
-   * UI.
-   */
-  description?: string;
-  /** The category of the event, which is displayed in the 'Event type' column on the audit log in the Confluence UI. */
-  category?: string;
-  /** Indicates whether the event was actioned by a system administrator. */
-  sysAdmin?: boolean;
-  affectedObject?: AffectedObject;
-  /** The values that were changed in the event. */
-  changedValues?: ChangedValue[];
-  /**
-   * Objects that were associated with the event. For example, if the event was a space permission change then the
-   * associated object would be the space.
-   */
-  associatedObjects?: AffectedObject[];
-}
diff --git a/src/api/models/availableContentStates.ts b/src/api/models/availableContentStates.ts
deleted file mode 100644
index c2381296..00000000
--- a/src/api/models/availableContentStates.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-import type { ContentState } from './contentState';
-
-export interface AvailableContentStates {
-  /** Space suggested content states that can be used in the space */
-  spaceContentStates: ContentState[];
-  customContentStates: ContentState[];
-}
diff --git a/src/api/models/blueprintTemplate.ts b/src/api/models/blueprintTemplate.ts
deleted file mode 100644
index 56617e2a..00000000
--- a/src/api/models/blueprintTemplate.ts
+++ /dev/null
@@ -1,21 +0,0 @@
-import type { ContentBody } from './contentBody';
-import type { GenericLinks } from './genericLinks';
-import type { Label } from './label';
-
-export interface BlueprintTemplate {
-  templateId: string;
-  originalTemplate: {
-    pluginKey: string;
-    moduleKey: string;
-  };
-  referencingBlueprint: string;
-  name: string;
-  description: string;
-  labels: Label[];
-  templateType: string;
-  body?: ContentBody;
-  _expandable: {
-    body?: string;
-  };
-  _links: GenericLinks;
-}
diff --git a/src/api/models/blueprintTemplateArray.ts b/src/api/models/blueprintTemplateArray.ts
deleted file mode 100644
index 75b32736..00000000
--- a/src/api/models/blueprintTemplateArray.ts
+++ /dev/null
@@ -1,10 +0,0 @@
-import type { BlueprintTemplate } from './blueprintTemplate';
-import type { GenericLinks } from './genericLinks';
-
-export interface BlueprintTemplateArray {
-  results: BlueprintTemplate[];
-  start: number;
-  limit: number;
-  size: number;
-  _links: GenericLinks;
-}
diff --git a/src/api/models/breadcrumb.ts b/src/api/models/breadcrumb.ts
deleted file mode 100644
index f137086f..00000000
--- a/src/api/models/breadcrumb.ts
+++ /dev/null
@@ -1,5 +0,0 @@
-export interface Breadcrumb {
-  label: string;
-  url: string;
-  separator: string;
-}
diff --git a/src/api/models/bulkUserLookup.ts b/src/api/models/bulkUserLookup.ts
deleted file mode 100644
index a9eeb534..00000000
--- a/src/api/models/bulkUserLookup.ts
+++ /dev/null
@@ -1,40 +0,0 @@
-import type { GenericLinks } from './genericLinks';
-import type { Icon } from './icon';
-import type { OperationCheckResult } from './operationCheckResult';
-import type { Space } from './space';
-
-export interface BulkUserLookup {
-  type: string;
-  /**
-   * This property is no longer available and will be removed from the documentation soon. Use `accountId` instead. See
-   * the [deprecation notice](/cloud/confluence/deprecation-notice-user-privacy-api-migration-guide/) for details.
-   */
-  username?: string;
-  /**
-   * This property is no longer available and will be removed from the documentation soon. Use `accountId` instead. See
-   * the [deprecation notice](/cloud/confluence/deprecation-notice-user-privacy-api-migration-guide/) for details.
-   */
-  userKey?: string;
-  /**
-   * The account ID of the user, which uniquely identifies the user across all Atlassian products. For example,
-   * `384093:32b4d9w0-f6a5-3535-11a3-9c8c88d10192`.
-   */
-  accountId: string;
-  /** The account type of the user, may return empty string if unavailable. */
-  accountType: string;
-  /** The email address of the user. Depending on the user's privacy setting, this may return an empty string. */
-  email: string;
-  /** The public name or nickname of the user. Will always contain a value. */
-  publicName: string;
-  profilePicture: Icon;
-  /** The display name of the user. Depending on the user's privacy setting, this may be the same as publicName. */
-  displayName: string;
-  operations?: OperationCheckResult[];
-  personalSpace?: Space;
-  _expandable: {
-    operations?: string;
-    details?: string;
-    personalSpace?: string;
-  };
-  _links: GenericLinks;
-}
diff --git a/src/api/models/bulkUserLookupArray.ts b/src/api/models/bulkUserLookupArray.ts
deleted file mode 100644
index 9f4368b7..00000000
--- a/src/api/models/bulkUserLookupArray.ts
+++ /dev/null
@@ -1,10 +0,0 @@
-import type { BulkUserLookup } from './bulkUserLookup';
-import type { GenericLinks } from './genericLinks';
-
-export interface BulkUserLookupArray {
-  results: BulkUserLookup[];
-  start: number;
-  limit: number;
-  size: number;
-  _links: GenericLinks;
-}
diff --git a/src/api/models/buttonLookAndFeel.ts b/src/api/models/buttonLookAndFeel.ts
deleted file mode 100644
index dc0a9725..00000000
--- a/src/api/models/buttonLookAndFeel.ts
+++ /dev/null
@@ -1,4 +0,0 @@
-export interface ButtonLookAndFeel {
-  backgroundColor: string;
-  color: string;
-}
diff --git a/src/api/models/changedValue.ts b/src/api/models/changedValue.ts
deleted file mode 100644
index 66581a88..00000000
--- a/src/api/models/changedValue.ts
+++ /dev/null
@@ -1,5 +0,0 @@
-export interface ChangedValue {
-  name: string;
-  oldValue: string;
-  newValue: string;
-}
diff --git a/src/api/models/connectModules.ts b/src/api/models/connectModules.ts
deleted file mode 100644
index 15bf47d1..00000000
--- a/src/api/models/connectModules.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-import type { AppDescriptor } from './appDescriptor';
-
-/**
- * A list of app modules in the same format as the `modules` property in the [app
- * descriptor](https://developer.atlassian.com/cloud/confluence/app-descriptor/).
- */
-export type ConnectModules = AppDescriptor[];
diff --git a/src/api/models/container.ts b/src/api/models/container.ts
deleted file mode 100644
index 67a886ad..00000000
--- a/src/api/models/container.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-/* eslint-disable @typescript-eslint/no-explicit-any */
-/**
- * Container for content. This can be either a space (containing a page or blogpost)* or a page/blog post (containing an
- * attachment or comment)
- */
-export type Container = Record;
diff --git a/src/api/models/containerLookAndFeel.ts b/src/api/models/containerLookAndFeel.ts
deleted file mode 100644
index b3a437d5..00000000
--- a/src/api/models/containerLookAndFeel.ts
+++ /dev/null
@@ -1,8 +0,0 @@
-export interface ContainerLookAndFeel {
-  background: string;
-  backgroundColor: string;
-  backgroundImage: string;
-  backgroundSize: string;
-  padding: string;
-  borderRadius: string;
-}
diff --git a/src/api/models/containerSummary.ts b/src/api/models/containerSummary.ts
deleted file mode 100644
index 2613b73b..00000000
--- a/src/api/models/containerSummary.ts
+++ /dev/null
@@ -1,4 +0,0 @@
-export interface ContainerSummary {
-  title: string;
-  displayUrl: string;
-}
diff --git a/src/api/models/content.ts b/src/api/models/content.ts
deleted file mode 100644
index e8968524..00000000
--- a/src/api/models/content.ts
+++ /dev/null
@@ -1,66 +0,0 @@
-import type { Container } from './container';
-import type { ContentBody } from './contentBody';
-import type { ContentChildren } from './contentChildren';
-import type { ContentChildType } from './contentChildType';
-import type { ContentHistory } from './contentHistory';
-import type { ContentRestriction } from './contentRestriction';
-import type { GenericLinks } from './genericLinks';
-import type { OperationCheckResult } from './operationCheckResult';
-import type { Space } from './space';
-import type { Version } from './version';
-
-/** Base object for all content types. */
-export interface Content {
-  id: string;
-  type: string;
-  status: string;
-  title: string;
-  space?: Space;
-  history?: ContentHistory;
-  version?: Version;
-  ancestors?: Content[];
-  operations?: OperationCheckResult[];
-  children?: ContentChildren;
-  childTypes?: ContentChildType;
-  descendants?: ContentChildren;
-  container?: Container;
-  body?: {
-    view?: ContentBody;
-    export_view?: ContentBody;
-    styled_view?: ContentBody;
-    storage?: ContentBody;
-    editor2?: ContentBody;
-    anonymous_export_view?: ContentBody;
-    atlas_doc_format?: ContentBody;
-    _expandable: {
-      editor?: string;
-      view?: string;
-      export_view?: string;
-      styled_view?: string;
-      storage?: string;
-      editor2?: string;
-      anonymous_export_view?: string;
-      atlas_doc_format?: string;
-    };
-  };
-  restrictions?: {
-    read?: ContentRestriction;
-    update?: ContentRestriction;
-    _links: GenericLinks;
-  };
-  _expandable: {
-    childTypes?: string;
-    container?: string;
-    metadata?: string;
-    operations?: string;
-    children?: string;
-    restrictions?: string;
-    history?: string;
-    ancestors?: string;
-    body?: string;
-    version?: string;
-    descendants?: string;
-    space?: string;
-  };
-  _links?: GenericLinks;
-}
diff --git a/src/api/models/contentArray.ts b/src/api/models/contentArray.ts
deleted file mode 100644
index 65f21f54..00000000
--- a/src/api/models/contentArray.ts
+++ /dev/null
@@ -1,10 +0,0 @@
-import type { Content } from './content';
-import type { GenericLinks } from './genericLinks';
-
-export interface ContentArray {
-  results: T[];
-  start?: number;
-  limit?: number;
-  size: number;
-  _links: GenericLinks;
-}
diff --git a/src/api/models/contentBlueprintDraft.ts b/src/api/models/contentBlueprintDraft.ts
deleted file mode 100644
index fb0f0d01..00000000
--- a/src/api/models/contentBlueprintDraft.ts
+++ /dev/null
@@ -1,29 +0,0 @@
-export interface ContentBlueprintDraft {
-  /** The version for the new content. */
-  version: {
-    /** The version number. Set this to `1`. */
-    number: number;
-  };
-  /** The title of the content. If you don't want to change the title, set this to the current title of the draft. */
-  title: string;
-  /** The type of content. Set this to `page`. */
-  type: string;
-  /** The status of the content. Set this to `current` or omit it altogether. */
-  status?: string;
-  /** The space for the content. */
-  space?: {
-    /** The key of the space */
-    key: string;
-  };
-  /**
-   * The new ancestor (i.e. parent page) for the content. If you have specified an ancestor, you must also specify a
-   * `space` property in the request body for the space that the ancestor is in.
-   *
-   * Note, if you specify more than one ancestor, the last ID in the array will be selected as the parent page for the
-   * content.
-   */
-  ancestors?: {
-    /** The content ID of the ancestor. */
-    id: string;
-  }[];
-}
diff --git a/src/api/models/contentBody.ts b/src/api/models/contentBody.ts
deleted file mode 100644
index 017fbafc..00000000
--- a/src/api/models/contentBody.ts
+++ /dev/null
@@ -1,12 +0,0 @@
-import type { EmbeddedContent } from './embeddedContent';
-import type { WebResourceDependencies } from './webResourceDependencies';
-
-export interface ContentBody {
-  value: string;
-  representation: string;
-  embeddedContent?: EmbeddedContent[];
-  webresource?: WebResourceDependencies;
-  _expandable: {
-    content?: string;
-  };
-}
diff --git a/src/api/models/contentBodyCreate.ts b/src/api/models/contentBodyCreate.ts
deleted file mode 100644
index c89f2667..00000000
--- a/src/api/models/contentBodyCreate.ts
+++ /dev/null
@@ -1,9 +0,0 @@
-/* eslint-disable @typescript-eslint/no-explicit-any */
-/** This object is used when creating or updating content. */
-export interface ContentBodyCreate {
-  /** The body of the content in the relevant format. */
-  value: string;
-  /** The content format type. Set the value of this property to the name of the format being used, e.g. 'storage'. */
-  representation: string;
-  additionalProperties?: any;
-}
diff --git a/src/api/models/contentBodyCreateStorage.ts b/src/api/models/contentBodyCreateStorage.ts
deleted file mode 100644
index 84002980..00000000
--- a/src/api/models/contentBodyCreateStorage.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-/** This object is used when creating or updating content. */
-export interface ContentBodyCreateStorage {
-  /** The body of the content in the relevant format. */
-  value: string;
-  /** The content format type. Set the value of this property to the name of the format being used, e.g. 'storage'. */
-  representation: string;
-}
diff --git a/src/api/models/contentChildType.ts b/src/api/models/contentChildType.ts
deleted file mode 100644
index 2d4a7d9f..00000000
--- a/src/api/models/contentChildType.ts
+++ /dev/null
@@ -1,26 +0,0 @@
-import type { GenericLinks } from './genericLinks';
-
-/**
- * Shows whether a piece of content has attachments, comments, or child pages.* Note, this doesn't actually contain the
- * child objects.
- */
-export interface ContentChildType {
-  attachment?: {
-    value: boolean;
-    _links: GenericLinks;
-  };
-  comment?: {
-    value: boolean;
-    _links: GenericLinks;
-  };
-  page?: {
-    value: boolean;
-    _links: GenericLinks;
-  };
-  _expandable: {
-    all?: string;
-    attachment?: string;
-    comment?: string;
-    page?: string;
-  };
-}
diff --git a/src/api/models/contentChildren.ts b/src/api/models/contentChildren.ts
deleted file mode 100644
index c69e9d46..00000000
--- a/src/api/models/contentChildren.ts
+++ /dev/null
@@ -1,14 +0,0 @@
-import type { ContentArray } from './contentArray';
-import type { GenericLinks } from './genericLinks';
-
-export interface ContentChildren {
-  attachment?: ContentArray;
-  comment?: ContentArray;
-  page?: ContentArray;
-  _expandable: {
-    attachment?: string;
-    comment?: string;
-    page?: string;
-  };
-  _links: GenericLinks;
-}
diff --git a/src/api/models/contentCreate.ts b/src/api/models/contentCreate.ts
deleted file mode 100644
index 643764e0..00000000
--- a/src/api/models/contentCreate.ts
+++ /dev/null
@@ -1,61 +0,0 @@
-import type { ContentBodyCreate } from './contentBodyCreate';
-
-export interface ContentCreate {
-  /** The ID of the draft content. Required when publishing a draft. */
-  id?: string;
-  title: string;
-  /** The type of the new content. Custom content types defined by apps are also supported. */
-  type: string | 'page' | 'blogpost' | 'comment';
-  /** The space that the content is being created in. */
-  space: {
-    /** The key of the space. */
-    key: string;
-  };
-  /** The status of the new content. */
-  status?: string;
-  /**
-   * The container of the content. Required if type is `comment` or certain types of custom content. If you are trying
-   * to create a comment that is a child of another comment, specify the parent comment in the ancestors field, not in
-   * this field.
-   */
-  container?: {
-    /** The `id` of the container. */
-    id: string;
-    /** The `type` of the container. */
-    type: string;
-  };
-  /**
-   * The parent content of the new content. If you are creating a top-level `page` or `comment`, this can be left blank.
-   * If you are creating a child page, this is where the parent page id goes. If you are creating a child comment, this
-   * is where the parent comment id goes. Only one parent content id can be specified.
-   */
-  ancestors?: {
-    /** The `id` of the parent content. */
-    id: string;
-  }[];
-  /**
-   * The body of the new content. Does not apply to attachments. Only one body format should be specified as the
-   * property for this object, e.g. `storage`.
-   *
-   * Note, `editor2` format is used by Atlassian only. `anonymous_export_view` is the same as 'export_view' format but
-   * only content viewable by an anonymous user is included.
-   */
-  body?: {
-    view?: ContentBodyCreate;
-    export_view?: ContentBodyCreate;
-    styled_view?: ContentBodyCreate;
-    storage?: ContentBodyCreate;
-    editor2?: ContentBodyCreate;
-    anonymous_export_view?: ContentBodyCreate;
-    atlas_doc_format?: ContentBodyCreate;
-  };
-  /**
-   * The new version for the created content.
-   *
-   * To get the current version number, use [Get content by ID](#api-content-id-get) and retrieve `version.number`.
-   */
-  version?: {
-    /** The version comment. */
-    message?: string;
-  };
-}
diff --git a/src/api/models/contentHistory.ts b/src/api/models/contentHistory.ts
deleted file mode 100644
index bdb79d23..00000000
--- a/src/api/models/contentHistory.ts
+++ /dev/null
@@ -1,23 +0,0 @@
-import type { GenericLinks } from './genericLinks';
-import type { User } from './user';
-import type { UsersUserKeys } from './usersUserKeys';
-import type { Version } from './version';
-
-export interface ContentHistory {
-  latest: boolean;
-  createdBy: User;
-  createdDate: string;
-  lastUpdated?: Version;
-  previousVersion?: Version;
-  contributors?: {
-    publishers?: UsersUserKeys;
-  };
-  nextVersion?: Version;
-  _expandable?: {
-    lastUpdated?: string;
-    previousVersion?: string;
-    contributors?: string;
-    nextVersion?: string;
-  };
-  _links?: GenericLinks;
-}
diff --git a/src/api/models/contentLookAndFeel.ts b/src/api/models/contentLookAndFeel.ts
deleted file mode 100644
index 27240ec7..00000000
--- a/src/api/models/contentLookAndFeel.ts
+++ /dev/null
@@ -1,9 +0,0 @@
-import type { ContainerLookAndFeel } from './containerLookAndFeel';
-import type { ScreenLookAndFeel } from './screenLookAndFeel';
-
-export interface ContentLookAndFeel {
-  screen: ScreenLookAndFeel;
-  container: ContainerLookAndFeel;
-  header: ContainerLookAndFeel;
-  body: ContainerLookAndFeel;
-}
diff --git a/src/api/models/contentPermissionRequest.ts b/src/api/models/contentPermissionRequest.ts
deleted file mode 100644
index 2534cb17..00000000
--- a/src/api/models/contentPermissionRequest.ts
+++ /dev/null
@@ -1,8 +0,0 @@
-import type { PermissionSubjectWithGroupId } from './permissionSubjectWithGroupId';
-
-/** This object represents the request for the content permission check API. */
-export interface ContentPermissionRequest {
-  subject: PermissionSubjectWithGroupId;
-  /** The content permission operation to check. */
-  operation: string;
-}
diff --git a/src/api/models/contentProperty.ts b/src/api/models/contentProperty.ts
deleted file mode 100644
index a7db4388..00000000
--- a/src/api/models/contentProperty.ts
+++ /dev/null
@@ -1,17 +0,0 @@
-import type { Content } from './content';
-import type { GenericLinks } from './genericLinks';
-
-export interface ContentProperty {
-  id: number;
-  key: string;
-  /** The value of the content property. This can be empty or a complex object. */
-  value: {};
-  version?: {
-    when: string;
-    message: string;
-    number: number;
-    minorEdit: boolean;
-  };
-  content?: Content;
-  _links: GenericLinks;
-}
diff --git a/src/api/models/contentPropertyArray.ts b/src/api/models/contentPropertyArray.ts
deleted file mode 100644
index 49a3f369..00000000
--- a/src/api/models/contentPropertyArray.ts
+++ /dev/null
@@ -1,10 +0,0 @@
-import type { ContentProperty } from './contentProperty';
-import type { GenericLinks } from './genericLinks';
-
-export interface ContentPropertyArray {
-  results: ContentProperty[];
-  start: number;
-  limit: number;
-  size: number;
-  _links: GenericLinks;
-}
diff --git a/src/api/models/contentPropertyCreate.ts b/src/api/models/contentPropertyCreate.ts
deleted file mode 100644
index 6789b66c..00000000
--- a/src/api/models/contentPropertyCreate.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-import type { PropertyValue } from './propertyValue';
-
-export interface ContentPropertyCreate {
-  /** The key of the new property. */
-  key: string;
-  value: PropertyValue;
-}
diff --git a/src/api/models/contentPropertyCreateNoKey.ts b/src/api/models/contentPropertyCreateNoKey.ts
deleted file mode 100644
index 94f04579..00000000
--- a/src/api/models/contentPropertyCreateNoKey.ts
+++ /dev/null
@@ -1,5 +0,0 @@
-import type { PropertyValue } from './propertyValue';
-
-export interface ContentPropertyCreateNoKey {
-  value: PropertyValue;
-}
diff --git a/src/api/models/contentPropertyUpdate.ts b/src/api/models/contentPropertyUpdate.ts
deleted file mode 100644
index 2fa5a8c9..00000000
--- a/src/api/models/contentPropertyUpdate.ts
+++ /dev/null
@@ -1,14 +0,0 @@
-export interface ContentPropertyUpdate {
-  /** The value of the content property. This can be empty or a complex object. */
-  value: {};
-  /** The version number of the property. */
-  version: {
-    /**
-     * The new version for the updated content property. Set this to the current version number incremented by one. To
-     * get the current version number, use 'Get content property' and retrieve `version.number`.
-     */
-    number: number;
-    /** If `minorEdit` is set to 'true', no notification email or activity stream will be generated for the change. */
-    minorEdit?: boolean;
-  };
-}
diff --git a/src/api/models/contentRestriction.ts b/src/api/models/contentRestriction.ts
deleted file mode 100644
index fc5d1bfa..00000000
--- a/src/api/models/contentRestriction.ts
+++ /dev/null
@@ -1,22 +0,0 @@
-import type { Content } from './content';
-import type { GenericLinks } from './genericLinks';
-import type { GroupArray } from './groupArray';
-import type { UserArray } from './userArray';
-
-export interface ContentRestriction {
-  operation: string;
-  restrictions?: {
-    user?: UserArray;
-    group?: GroupArray;
-    _expandable?: {
-      user?: string;
-      group?: string;
-    };
-  };
-  content?: Content;
-  _expandable: {
-    restrictions?: string;
-    content?: string;
-  };
-  _links: GenericLinks;
-}
diff --git a/src/api/models/contentRestrictionArray.ts b/src/api/models/contentRestrictionArray.ts
deleted file mode 100644
index 9398e92a..00000000
--- a/src/api/models/contentRestrictionArray.ts
+++ /dev/null
@@ -1,12 +0,0 @@
-import type { ContentRestriction } from './contentRestriction';
-import type { GenericLinks } from './genericLinks';
-
-export interface ContentRestrictionArray {
-  results: ContentRestriction[];
-  start: number;
-  limit: number;
-  size: number;
-  /** This property is used by the UI to figure out whether a set of restrictions has changed. */
-  restrictionsHash: string;
-  _links: GenericLinks;
-}
diff --git a/src/api/models/contentRestrictionUpdate.ts b/src/api/models/contentRestrictionUpdate.ts
deleted file mode 100644
index 68c36980..00000000
--- a/src/api/models/contentRestrictionUpdate.ts
+++ /dev/null
@@ -1,45 +0,0 @@
-export interface ContentRestrictionUpdate {
-  /** The restriction operation applied to content. */
-  operation: string;
-  /**
-   * The users/groups that the restrictions will be applied to. At least one of `user` or `group` must be specified for
-   * this object.
-   */
-  restrictions: {
-    /**
-     * The users that the restrictions will be applied to. This array must have at least one item, otherwise it should
-     * be omitted.
-     */
-    user?: {
-      /** Set to 'known'. */
-      type: string;
-      /**
-       * This property is no longer available and will be removed from the documentation soon. Use `accountId` instead.
-       * See the [deprecation notice](/cloud/confluence/deprecation-notice-user-privacy-api-migration-guide/) for
-       * details.
-       */
-      username?: string;
-      /**
-       * This property is no longer available and will be removed from the documentation soon. Use `accountId` instead.
-       * See the [deprecation notice](/cloud/confluence/deprecation-notice-user-privacy-api-migration-guide/) for
-       * details.
-       */
-      userKey?: string;
-      /**
-       * The account ID of the user, which uniquely identifies the user across all Atlassian products. For example,
-       * `384093:32b4d9w0-f6a5-3535-11a3-9c8c88d10192`.
-       */
-      accountId: string;
-    }[];
-    /**
-     * The groups that the restrictions will be applied to. This array must have at least one item, otherwise it should
-     * be omitted.
-     */
-    group?: {
-      /** Set to 'group'. */
-      type: string;
-      /** The name of the group. */
-      name: string;
-    }[];
-  };
-}
diff --git a/src/api/models/contentRestrictionUpdateArray.ts b/src/api/models/contentRestrictionUpdateArray.ts
deleted file mode 100644
index c69f4fc2..00000000
--- a/src/api/models/contentRestrictionUpdateArray.ts
+++ /dev/null
@@ -1,3 +0,0 @@
-import type { ContentRestrictionUpdate } from './contentRestrictionUpdate';
-
-export type ContentRestrictionUpdateArray = ContentRestrictionUpdate[];
diff --git a/src/api/models/contentState.ts b/src/api/models/contentState.ts
deleted file mode 100644
index 5b357059..00000000
--- a/src/api/models/contentState.ts
+++ /dev/null
@@ -1,8 +0,0 @@
-export interface ContentState {
-  /** Identifier of content state. If 0, 1, or 2, this is a default space state */
-  id: number;
-  /** Name of content state. */
-  name: string;
-  /** Hex string representing color of state */
-  color: string;
-}
diff --git a/src/api/models/contentStateResponse.ts b/src/api/models/contentStateResponse.ts
deleted file mode 100644
index 71a52000..00000000
--- a/src/api/models/contentStateResponse.ts
+++ /dev/null
@@ -1,8 +0,0 @@
-import type { ContentState } from './contentState';
-
-export interface ContentStateResponse {
-  /** Null or content state */
-  contentState?: ContentState;
-  /** Timestamp of last publish event where content state changed */
-  lastUpdated?: string;
-}
diff --git a/src/api/models/contentStateRestInput.ts b/src/api/models/contentStateRestInput.ts
deleted file mode 100644
index d7570324..00000000
--- a/src/api/models/contentStateRestInput.ts
+++ /dev/null
@@ -1,11 +0,0 @@
-export interface ContentStateRestInput {
-  /** Name of content state. Maximum 20 characters. */
-  name?: string;
-  /**
-   * Color of state. Must be in 6 digit hex form (#FFFFFF). The default colors offered in the UI are: #ff7452 (red),
-   * #2684ff (blue), #ffc400 (yellow), #57d9a3 (green), and #8777d9 (purple)
-   */
-  color?: string;
-  /** Id of state. This can be 0,1, or 2 if you wish to specify a default space state. */
-  stateId?: string;
-}
diff --git a/src/api/models/contentStateSettings.ts b/src/api/models/contentStateSettings.ts
deleted file mode 100644
index 64089036..00000000
--- a/src/api/models/contentStateSettings.ts
+++ /dev/null
@@ -1,12 +0,0 @@
-import type { ContentState } from './contentState';
-
-export interface ContentStateSettings {
-  /** Whether users can place content states on any pages and blog posts in the space */
-  contentStatesAllowed: boolean;
-  /** Whether users can create custom states on the fly on pages and blog posts */
-  customContentStatesAllowed: boolean;
-  /** Whether space content states are allowed */
-  spaceContentStatesAllowed: boolean;
-  /** Space content states that users in the space can choose from */
-  spaceContentStates?: ContentState[];
-}
diff --git a/src/api/models/contentTemplate.ts b/src/api/models/contentTemplate.ts
deleted file mode 100644
index d450a6d4..00000000
--- a/src/api/models/contentTemplate.ts
+++ /dev/null
@@ -1,16 +0,0 @@
-import type { ContentBody } from './contentBody';
-import type { GenericLinks } from './genericLinks';
-import type { Label } from './label';
-
-export interface ContentTemplate {
-  templateId: string;
-  name: string;
-  description: string;
-  labels: Label[];
-  templateType: string;
-  body?: ContentBody;
-  _expandable: {
-    body?: string;
-  };
-  _links: GenericLinks;
-}
diff --git a/src/api/models/contentTemplateArray.ts b/src/api/models/contentTemplateArray.ts
deleted file mode 100644
index 2cf836b7..00000000
--- a/src/api/models/contentTemplateArray.ts
+++ /dev/null
@@ -1,10 +0,0 @@
-import type { ContentTemplate } from './contentTemplate';
-import type { GenericLinks } from './genericLinks';
-
-export interface ContentTemplateArray {
-  results: ContentTemplate[];
-  start: number;
-  limit: number;
-  size: number;
-  _links: GenericLinks;
-}
diff --git a/src/api/models/contentTemplateBodyCreate.ts b/src/api/models/contentTemplateBodyCreate.ts
deleted file mode 100644
index 74b06cda..00000000
--- a/src/api/models/contentTemplateBodyCreate.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-import type { ContentBodyCreate } from './contentBodyCreate';
-
-/** This object is used when creating or updating content. */
-export interface ContentTemplateBodyCreate {
-  storage?: ContentBodyCreate;
-}
diff --git a/src/api/models/contentTemplateCreate.ts b/src/api/models/contentTemplateCreate.ts
deleted file mode 100644
index 9d598cad..00000000
--- a/src/api/models/contentTemplateCreate.ts
+++ /dev/null
@@ -1,22 +0,0 @@
-import type { ContentTemplateBodyCreate } from './contentTemplateBodyCreate';
-import type { Label } from './label';
-
-/** This object is used to create content templates. */
-export interface ContentTemplateCreate {
-  /** The name of the new template. */
-  name: string;
-  /** The type of the new template. Set to `page`. */
-  templateType: string;
-  body: ContentTemplateBodyCreate;
-  /** A description of the new template. */
-  description?: string;
-  /** Labels for the new template. */
-  labels?: Label[];
-  /**
-   * The key for the space of the new template. Only applies to space templates. If the spaceKey is not specified, the
-   * template will be created as a global template.
-   */
-  space?: {
-    key: string;
-  };
-}
diff --git a/src/api/models/contentTemplateUpdate.ts b/src/api/models/contentTemplateUpdate.ts
deleted file mode 100644
index 9e03a268..00000000
--- a/src/api/models/contentTemplateUpdate.ts
+++ /dev/null
@@ -1,24 +0,0 @@
-import type { ContentBodyCreate } from './contentBodyCreate';
-import type { Label } from './label';
-
-/** This object is used to update content templates. */
-export interface ContentTemplateUpdate {
-  /** The ID of the template being updated. */
-  templateId: string;
-  /** The name of the template. Set to the current `name` if this field is not being updated. */
-  name: string;
-  /** The type of the template. Set to `page`. */
-  templateType: string;
-  body: ContentBodyCreate;
-  /** A description of the template. */
-  description?: string;
-  /** Labels for the template. */
-  labels?: Label[];
-  /**
-   * The key for the space of the template. Required if the template is a space template. Set this to the current
-   * `space.key`.
-   */
-  space?: {
-    key: string;
-  };
-}
diff --git a/src/api/models/contentUpdate.ts b/src/api/models/contentUpdate.ts
deleted file mode 100644
index aba00a6a..00000000
--- a/src/api/models/contentUpdate.ts
+++ /dev/null
@@ -1,45 +0,0 @@
-import type { ContentBodyCreate } from './contentBodyCreate';
-import type { ContentBodyCreateStorage } from './contentBodyCreateStorage';
-
-export interface ContentUpdate {
-  /**
-   * The new version for the updated content. Set this to the current version number incremented by one, unless you are
-   * changing the status to 'draft' which must have a version number of 1.
-   *
-   * To get the current version number, use [Get content by ID](#api-content-id-get) and retrieve `version.number`.
-   */
-  version: {
-    /** The version number. */
-    number: number;
-    /** The version comment. */
-    message?: string;
-  };
-  /** The updated title of the content. If you are not changing this field, set this to the current `title`. */
-  title: string;
-  /** The type of content. Set this to the current type of the content. */
-  type: string;
-  /**
-   * The updated status of the content. Note, if you change the status of a page from 'current' to 'draft' and it has an
-   * existing draft, the existing draft will be deleted in favor of the updated page.
-   */
-  status?: 'current' | 'trashed' | 'historical' | 'draft' | string;
-  /** The new parent for the content. Only one parent content 'id' can be specified. */
-  ancestors?: {
-    /** The `id` of the parent content. */
-    id: string;
-  }[];
-  /**
-   * The updated body of the content. Does not apply to attachments. If you are not sure how to generate these formats,
-   * you can create a page in the Confluence application, retrieve the content using [Get content](#api-content-get),
-   * and expand the desired content format, e.g. `expand=body.storage`.
-   */
-  body?: {
-    view?: ContentBodyCreate;
-    export_view?: ContentBodyCreate;
-    styled_view?: ContentBodyCreate;
-    storage?: ContentBodyCreateStorage;
-    editor2?: ContentBodyCreate;
-    anonymous_export_view?: ContentBodyCreate;
-    atlas_doc_format?: ContentBodyCreate;
-  };
-}
diff --git a/src/api/models/copyPageHierarchyRequest.ts b/src/api/models/copyPageHierarchyRequest.ts
deleted file mode 100644
index dfd46f89..00000000
--- a/src/api/models/copyPageHierarchyRequest.ts
+++ /dev/null
@@ -1,18 +0,0 @@
-import type { CopyPageHierarchyTitleOptions } from './copyPageHierarchyTitleOptions';
-
-export interface CopyPageHierarchyRequest {
-  /** If set to `true`, attachments are copied to the destination page. */
-  copyAttachments?: boolean;
-  /** If set to `true`, page permissions are copied to the destination page. */
-  copyPermissions?: boolean;
-  /** If set to `true`, content properties are copied to the destination page. */
-  copyProperties?: boolean;
-  /** If set to `true`, labels are copied to the destination page. */
-  copyLabels?: boolean;
-  /** If set to `true`, custom contents are copied to the destination page. */
-  copyCustomContents?: boolean;
-  /** If set to `true`, descendants are copied to the destination page. */
-  copyDescendants?: boolean;
-  destinationPageId: string;
-  titleOptions?: CopyPageHierarchyTitleOptions;
-}
diff --git a/src/api/models/copyPageHierarchyTitleOptions.ts b/src/api/models/copyPageHierarchyTitleOptions.ts
deleted file mode 100644
index 02faaa86..00000000
--- a/src/api/models/copyPageHierarchyTitleOptions.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-/** Required for copying page in the same space. */
-export interface CopyPageHierarchyTitleOptions {
-  prefix?: string;
-  replace?: string;
-  search?: string;
-}
diff --git a/src/api/models/copyPageRequest.ts b/src/api/models/copyPageRequest.ts
deleted file mode 100644
index 21a034ff..00000000
--- a/src/api/models/copyPageRequest.ts
+++ /dev/null
@@ -1,23 +0,0 @@
-import type { ContentBodyCreate } from './contentBodyCreate';
-import type { CopyPageRequestDestination } from './copyPageRequestDestination';
-
-export interface CopyPageRequest {
-  /** If set to `true`, attachments are copied to the destination page. */
-  copyAttachments?: boolean;
-  /** If set to `true`, page permissions are copied to the destination page. */
-  copyPermissions?: boolean;
-  /** If set to `true`, content properties are copied to the destination page. */
-  copyProperties?: boolean;
-  /** If set to `true`, labels are copied to the destination page. */
-  copyLabels?: boolean;
-  /** If set to `true`, custom contents are copied to the destination page. */
-  copyCustomContents?: boolean;
-  destination: CopyPageRequestDestination;
-  /** If defined, this will replace the title of the destination page. */
-  pageTitle?: string;
-  /** If defined, this will replace the body of the destination page. */
-  body?: {
-    storage?: ContentBodyCreate;
-    editor2?: ContentBodyCreate;
-  };
-}
diff --git a/src/api/models/copyPageRequestDestination.ts b/src/api/models/copyPageRequestDestination.ts
deleted file mode 100644
index f548218b..00000000
--- a/src/api/models/copyPageRequestDestination.ts
+++ /dev/null
@@ -1,12 +0,0 @@
-/**
- * Defines where the page will be copied to, and can be one of the following types.*
- *
- * - `parent_page`: page will be copied as a child of the specified parent page
- * - `space`: page will be copied to the specified space as a root page on the space
- * - `existing_page`: page will be copied and replace the specified page
- */
-export interface CopyPageRequestDestination {
-  type: string;
-  /** The space key for `space` type, and content id for `parent_page` and `existing_page` */
-  value: string;
-}
diff --git a/src/api/models/createdAttachment.ts b/src/api/models/createdAttachment.ts
deleted file mode 100644
index 38f42a8c..00000000
--- a/src/api/models/createdAttachment.ts
+++ /dev/null
@@ -1,8 +0,0 @@
-import type { Attachment } from './attachment';
-import type { AttachmentContainer } from './attachmentContainer';
-import type { Version } from './version';
-
-export interface CreatedAttachment extends Attachment {
-  version: Version;
-  container: AttachmentContainer;
-}
diff --git a/src/api/models/embeddable.ts b/src/api/models/embeddable.ts
deleted file mode 100644
index 4ee777de..00000000
--- a/src/api/models/embeddable.ts
+++ /dev/null
@@ -1,2 +0,0 @@
-/* eslint-disable @typescript-eslint/no-explicit-any */
-export type Embeddable = Record;
diff --git a/src/api/models/embeddedContent.ts b/src/api/models/embeddedContent.ts
deleted file mode 100644
index e21b8345..00000000
--- a/src/api/models/embeddedContent.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-import type { Embeddable } from './embeddable';
-
-export interface EmbeddedContent {
-  entityId?: number;
-  entity?: Embeddable;
-}
diff --git a/src/api/models/genericLinks.ts b/src/api/models/genericLinks.ts
deleted file mode 100644
index f1045253..00000000
--- a/src/api/models/genericLinks.ts
+++ /dev/null
@@ -1,11 +0,0 @@
-/* eslint-disable @typescript-eslint/no-explicit-any */
-export type GenericLinks = Record & {
-  self: string;
-  next?: string;
-  tinyui?: string;
-  editui?: string;
-  webui?: string;
-  base?: string;
-  context?: string;
-  download?: string;
-};
diff --git a/src/api/models/getRestrictionsByOperation.ts b/src/api/models/getRestrictionsByOperation.ts
deleted file mode 100644
index 41237170..00000000
--- a/src/api/models/getRestrictionsByOperation.ts
+++ /dev/null
@@ -1,5 +0,0 @@
-import type { GenericLinks } from './genericLinks';
-
-export interface GetRestrictionsByOperation {
-  _links: GenericLinks;
-}
diff --git a/src/api/models/getViewers.ts b/src/api/models/getViewers.ts
deleted file mode 100644
index 731dadcc..00000000
--- a/src/api/models/getViewers.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-export interface GetViewers {
-  /** The content ID. */
-  id?: number;
-  /** The total number of distinct viewers for the content. */
-  count?: number;
-}
diff --git a/src/api/models/getViews.ts b/src/api/models/getViews.ts
deleted file mode 100644
index 7cdd3f8d..00000000
--- a/src/api/models/getViews.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-export interface GetViews {
-  /** The content ID. */
-  id?: number;
-  /** The total number of views for the content. */
-  count?: number;
-}
diff --git a/src/api/models/group.ts b/src/api/models/group.ts
deleted file mode 100644
index 5c62b209..00000000
--- a/src/api/models/group.ts
+++ /dev/null
@@ -1,8 +0,0 @@
-import type { GenericLinks } from './genericLinks';
-
-export interface Group {
-  type: string;
-  name: string;
-  id: string;
-  _links: GenericLinks;
-}
diff --git a/src/api/models/groupArray.ts b/src/api/models/groupArray.ts
deleted file mode 100644
index d77106a2..00000000
--- a/src/api/models/groupArray.ts
+++ /dev/null
@@ -1,8 +0,0 @@
-import type { Group } from './group';
-
-export interface GroupArray {
-  results: Group[];
-  start: number;
-  limit: number;
-  size: number;
-}
diff --git a/src/api/models/groupArrayWithLinks.ts b/src/api/models/groupArrayWithLinks.ts
deleted file mode 100644
index c7c944a3..00000000
--- a/src/api/models/groupArrayWithLinks.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-/* eslint-disable @typescript-eslint/no-explicit-any */
-import type { GroupArray } from './groupArray';
-
-/** Same as GroupArray but with `_links` property. */
-export interface GroupArrayWithLinks extends GroupArray {
-  _links: Record;
-}
diff --git a/src/api/models/groupCreate.ts b/src/api/models/groupCreate.ts
deleted file mode 100644
index fe2b9462..00000000
--- a/src/api/models/groupCreate.ts
+++ /dev/null
@@ -1,4 +0,0 @@
-export interface GroupCreate {
-  type: string;
-  name: string;
-}
diff --git a/src/api/models/groupName.ts b/src/api/models/groupName.ts
deleted file mode 100644
index ebeab27b..00000000
--- a/src/api/models/groupName.ts
+++ /dev/null
@@ -1,3 +0,0 @@
-export interface GroupName {
-  name: string;
-}
diff --git a/src/api/models/headerLookAndFeel.ts b/src/api/models/headerLookAndFeel.ts
deleted file mode 100644
index eabf286f..00000000
--- a/src/api/models/headerLookAndFeel.ts
+++ /dev/null
@@ -1,11 +0,0 @@
-import type { ButtonLookAndFeel } from './buttonLookAndFeel';
-import type { NavigationLookAndFeel } from './navigationLookAndFeel';
-import type { SearchFieldLookAndFeel } from './searchFieldLookAndFeel';
-
-export interface HeaderLookAndFeel {
-  backgroundColor: string;
-  button: ButtonLookAndFeel;
-  primaryNavigation: NavigationLookAndFeel;
-  secondaryNavigation: NavigationLookAndFeel;
-  search: SearchFieldLookAndFeel;
-}
diff --git a/src/api/models/horizontalHeaderLookAndFeel.ts b/src/api/models/horizontalHeaderLookAndFeel.ts
deleted file mode 100644
index 4fc6c7b1..00000000
--- a/src/api/models/horizontalHeaderLookAndFeel.ts
+++ /dev/null
@@ -1,12 +0,0 @@
-import type { ButtonLookAndFeel } from './buttonLookAndFeel';
-import type { NavigationLookAndFeel } from './navigationLookAndFeel';
-import type { SearchFieldLookAndFeel } from './searchFieldLookAndFeel';
-import type { TopNavigationLookAndFeel } from './topNavigationLookAndFeel';
-
-export interface HorizontalHeaderLookAndFeel {
-  backgroundColor: string;
-  button?: ButtonLookAndFeel;
-  primaryNavigation: TopNavigationLookAndFeel;
-  secondaryNavigation?: NavigationLookAndFeel;
-  search?: SearchFieldLookAndFeel;
-}
diff --git a/src/api/models/icon.ts b/src/api/models/icon.ts
deleted file mode 100644
index 5e602646..00000000
--- a/src/api/models/icon.ts
+++ /dev/null
@@ -1,10 +0,0 @@
-/**
- * This object represents an icon. If used as a profilePicture, this may be returned as null, depending on the user's
- * privacy setting.
- */
-export interface Icon {
-  path: string;
-  width: number;
-  height: number;
-  isDefault: boolean;
-}
diff --git a/src/api/models/index.ts b/src/api/models/index.ts
deleted file mode 100644
index 9cac4f8a..00000000
--- a/src/api/models/index.ts
+++ /dev/null
@@ -1,161 +0,0 @@
-export * from './accountId';
-export * from './accountIdEmailRecord';
-export * from './accountIdEmailRecordArray';
-export * from './addContentRestriction';
-export * from './addContentRestrictionUpdateArray';
-export * from './affectedObject';
-export * from './appDescriptor';
-export * from './asyncContentBody';
-export * from './asyncId';
-export * from './attachment';
-export * from './attachmentContainer';
-export * from './attachmentMetadata';
-export * from './auditRecord';
-export * from './auditRecordArray';
-export * from './auditRecordCreate';
-export * from './availableContentStates';
-export * from './blueprintTemplate';
-export * from './blueprintTemplateArray';
-export * from './breadcrumb';
-export * from './bulkUserLookup';
-export * from './bulkUserLookupArray';
-export * from './buttonLookAndFeel';
-export * from './changedValue';
-export * from './connectModules';
-export * from './container';
-export * from './containerLookAndFeel';
-export * from './containerSummary';
-export * from './content';
-export * from './contentArray';
-export * from './contentBlueprintDraft';
-export * from './contentBody';
-export * from './contentBodyCreate';
-export * from './contentBodyCreateStorage';
-export * from './contentChildren';
-export * from './contentChildType';
-export * from './contentCreate';
-export * from './contentHistory';
-export * from './contentLookAndFeel';
-export * from './contentPermissionRequest';
-export * from './contentProperty';
-export * from './contentPropertyArray';
-export * from './contentPropertyCreate';
-export * from './contentPropertyCreateNoKey';
-export * from './contentPropertyUpdate';
-export * from './contentRestriction';
-export * from './contentRestrictionArray';
-export * from './contentRestrictionUpdate';
-export * from './contentRestrictionUpdateArray';
-export * from './contentState';
-export * from './contentStateResponse';
-export * from './contentStateRestInput';
-export * from './contentStateSettings';
-export * from './contentTemplate';
-export * from './contentTemplateArray';
-export * from './contentTemplateBodyCreate';
-export * from './contentTemplateCreate';
-export * from './contentTemplateUpdate';
-export * from './contentUpdate';
-export * from './copyPageHierarchyRequest';
-export * from './copyPageHierarchyTitleOptions';
-export * from './copyPageRequest';
-export * from './copyPageRequestDestination';
-export * from './createdAttachment';
-export * from './embeddable';
-export * from './embeddedContent';
-export * from './genericLinks';
-export * from './getRestrictionsByOperation';
-export * from './getViewers';
-export * from './getViews';
-export * from './group';
-export * from './groupArray';
-export * from './groupArrayWithLinks';
-export * from './groupCreate';
-export * from './groupName';
-export * from './headerLookAndFeel';
-export * from './horizontalHeaderLookAndFeel';
-export * from './icon';
-export * from './label';
-export * from './labelArray';
-export * from './labelCreate';
-export * from './labelCreateArray';
-export * from './labelDetails';
-export * from './labeledContent';
-export * from './labeledContentPageResponse';
-export * from './labeledContentType';
-export * from './lifecycle';
-export * from './longTask';
-export * from './longTaskStatus';
-export * from './longTaskStatusArray';
-export * from './longTaskStatusWithLinks';
-export * from './lookAndFeel';
-export * from './lookAndFeelSelection';
-export * from './lookAndFeelSettings';
-export * from './macroInstance';
-export * from './menusLookAndFeel';
-export * from './message';
-export * from './migratedUser';
-export * from './migratedUserArray';
-export * from './movePage';
-export * from './navigationLookAndFeel';
-export * from './operationCheckResult';
-export * from './permissionCheckResponse';
-export * from './permissionSubject';
-export * from './permissionSubjectWithGroupId';
-export * from './propertyValue';
-export * from './relation';
-export * from './relationArray';
-export * from './relationData';
-export * from './retentionPeriod';
-export * from './screenLookAndFeel';
-export * from './searchFieldLookAndFeel';
-export * from './searchPageResponseSearchResult';
-export * from './searchResult';
-export * from './space';
-export * from './spaceArray';
-export * from './spaceCreate';
-export * from './spaceDescription';
-export * from './spaceDescriptionCreate';
-export * from './spacePermission';
-export * from './spacePermissionCreate';
-export * from './spacePermissionCustomContent';
-export * from './spacePermissionRequest';
-export * from './spacePermissionV2';
-export * from './spacePrivateCreate';
-export * from './spaceProperty';
-export * from './spacePropertyArray';
-export * from './spacePropertyCreate';
-export * from './spacePropertyCreateNoKey';
-export * from './spacePropertyUpdate';
-export * from './spaceSettings';
-export * from './spaceSettingsUpdate';
-export * from './spaceUpdate';
-export * from './spaceWatch';
-export * from './spaceWatchArray';
-export * from './spaceWatchUser';
-export * from './superBatchWebResources';
-export * from './systemInfoEntity';
-export * from './task';
-export * from './taskPageResponse';
-export * from './taskStatusUpdate';
-export * from './theme';
-export * from './themeArray';
-export * from './themeNoLinks';
-export * from './themeUpdate';
-export * from './topNavigationLookAndFeel';
-export * from './user';
-export * from './userAnonymous';
-export * from './userArray';
-export * from './userProperty';
-export * from './userPropertyCreate';
-export * from './userPropertyKeyArray';
-export * from './userPropertyUpdate';
-export * from './usersUserKeys';
-export * from './userWatch';
-export * from './version';
-export * from './versionArray';
-export * from './versionRestore';
-export * from './watch';
-export * from './watchArray';
-export * from './watchUser';
-export * from './webResourceDependencies';
diff --git a/src/api/models/label.ts b/src/api/models/label.ts
deleted file mode 100644
index df6ec35e..00000000
--- a/src/api/models/label.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-export interface Label {
-  prefix: string;
-  name: string;
-  id: string;
-  label: string;
-}
diff --git a/src/api/models/labelArray.ts b/src/api/models/labelArray.ts
deleted file mode 100644
index 75283389..00000000
--- a/src/api/models/labelArray.ts
+++ /dev/null
@@ -1,10 +0,0 @@
-import type { GenericLinks } from './genericLinks';
-import type { Label } from './label';
-
-export interface LabelArray {
-  results: Label[];
-  start: number;
-  limit: number;
-  size: number;
-  _links: GenericLinks;
-}
diff --git a/src/api/models/labelCreate.ts b/src/api/models/labelCreate.ts
deleted file mode 100644
index 5cff70de..00000000
--- a/src/api/models/labelCreate.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-export interface LabelCreate {
-  /** The prefix for the label. */
-  prefix: 'global' | 'my' | 'team' | string;
-  /** The name of the label, which will be shown in the UI. */
-  name: string;
-}
diff --git a/src/api/models/labelCreateArray.ts b/src/api/models/labelCreateArray.ts
deleted file mode 100644
index 06821fa7..00000000
--- a/src/api/models/labelCreateArray.ts
+++ /dev/null
@@ -1,3 +0,0 @@
-import type { LabelCreate } from './labelCreate';
-
-export type LabelCreateArray = LabelCreate[];
diff --git a/src/api/models/labelDetails.ts b/src/api/models/labelDetails.ts
deleted file mode 100644
index ea09975a..00000000
--- a/src/api/models/labelDetails.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-import type { Label } from './label';
-import type { LabeledContentPageResponse } from './labeledContentPageResponse';
-
-export interface LabelDetails {
-  label: Label;
-  associatedContents?: LabeledContentPageResponse;
-}
diff --git a/src/api/models/labeledContent.ts b/src/api/models/labeledContent.ts
deleted file mode 100644
index 66345b72..00000000
--- a/src/api/models/labeledContent.ts
+++ /dev/null
@@ -1,8 +0,0 @@
-import type { LabeledContentType } from './labeledContentType';
-
-export interface LabeledContent {
-  contentType: LabeledContentType;
-  contentId: number;
-  /** Title of the content. */
-  title: string;
-}
diff --git a/src/api/models/labeledContentPageResponse.ts b/src/api/models/labeledContentPageResponse.ts
deleted file mode 100644
index d80bc8af..00000000
--- a/src/api/models/labeledContentPageResponse.ts
+++ /dev/null
@@ -1,8 +0,0 @@
-import type { LabeledContent } from './labeledContent';
-
-export interface LabeledContentPageResponse {
-  results: LabeledContent[];
-  start?: number;
-  limit?: number;
-  size: number;
-}
diff --git a/src/api/models/labeledContentType.ts b/src/api/models/labeledContentType.ts
deleted file mode 100644
index fb633197..00000000
--- a/src/api/models/labeledContentType.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-export enum LabeledContentType {
-  Page = 'page',
-  Blogpost = 'blogpost',
-  Attachment = 'attachment',
-  PageTemplate = 'page_template',
-}
diff --git a/src/api/models/lifecycle.ts b/src/api/models/lifecycle.ts
deleted file mode 100644
index 7eb3df11..00000000
--- a/src/api/models/lifecycle.ts
+++ /dev/null
@@ -1,66 +0,0 @@
-/**
- * Allows an app to register callbacks for events that occur in the lifecycle of an installation. When a lifecycle event
- * is fired, a POST request will be made to the appropriate URL registered for the event.
- *
- * The installed lifecycle callback is an integral part of the installation process of an app, whereas the remaining
- * lifecycle events are essentially webhooks.
- *
- * Each property in this object is a URL relative to the app's base URL.
- */
-export interface Lifecycle {
-  /** App key that was installed into the Atlassian Product, as it appears in your app's descriptor. */
-  key?: string;
-
-  /**
-   * Identifying key for the Atlassian product tenant that the app was installed into. This will never change for an
-   * Atlassian product tenant. However, be aware that importing data into a site will result in a new tenant. In this
-   * case, any app installations into the new tenant (using the same baseUrl as the previous tenant) will result in an
-   * installation payload containing a different clientKey. Determining the contract between the instance and app in
-   * this situation is tracked by [AC-1528](https://ecosystem.atlassian.net/browse/AC-1528) in the Connect backlog.
-   */
-  clientKey?: string;
-
-  /**
-   * The account ID for identifying users in the `sub` claim sent in JWT during calls. This is the user associated with
-   * the relevant action, and may not be present if there is no logged in user.
-   */
-  accountId?: string;
-
-  /**
-   * Use this string to sign outgoing JWT tokens and validate incoming JWT tokens. Optional: and may not be present on
-   * non-JWT app installations, and is only sent on the `installed` event. All instances of your app use the same shared
-   * secret.
-   */
-  sharedSecret?: string;
-
-  /** URL prefix for this Atlassian product instance. All of its REST endpoints begin with this `baseUrl`. */
-  baseUrl: string;
-
-  /**
-   * If the Atlassian product instance has an associated custom domain, this is the URL through which users will access
-   * the product. Any links which an app renders server-side should use this as the prefix of the link. This ensures
-   * links are rendered in the same context as the remainder of the user's site.
-   *
-   * This field may not be present, in which case the baseUrl value should be used. API requests from your App should
-   * always use the baseUrl value and not be based on the URL specified here.
-   */
-  displayUrl?: string;
-
-  /** Identifies the category of Atlassian product, e.g. `jira` or `confluence`. */
-  productType?: string;
-
-  /** The host product description - this is customisable by an instance administrator. */
-  description?: string;
-
-  /**
-   * Also known as the SEN, the service entitlement number is the app license ID. This attribute will only be included
-   * during installation of a paid app.
-   */
-  serviceEntitlementNumber?: string;
-
-  /**
-   * The OAuth 2.0 client ID for your app. For more information, see [OAuth 2.0 - JWT Bearer token authorization grant
-   * type](https://developer.atlassian.com/cloud/jira/platform/oauth-2-jwt-bearer-token-authorization-grant-type/)
-   */
-  oauthClientId?: string;
-}
diff --git a/src/api/models/longTask.ts b/src/api/models/longTask.ts
deleted file mode 100644
index b3d37c08..00000000
--- a/src/api/models/longTask.ts
+++ /dev/null
@@ -1,8 +0,0 @@
-export interface LongTask {
-  /** A unique identifier for the long task */
-  id: string;
-  links: {
-    /** The URL to retrieve status of long task. */
-    status?: string;
-  };
-}
diff --git a/src/api/models/longTaskStatus.ts b/src/api/models/longTaskStatus.ts
deleted file mode 100644
index 8df79a17..00000000
--- a/src/api/models/longTaskStatus.ts
+++ /dev/null
@@ -1,40 +0,0 @@
-import type { Message } from './message';
-
-/**
- * Current status of a long running task*
- *
- * Status keys:
- *
- * - `ERROR_UNKNOWN` - Generic error
- * - `ERROR_LOCK_FAILED` - Could not get the lock on destination space
- * - `ERROR_RELINK` - Error when relink pages/attachments
- * - `ERROR_COPY_PAGE` - Error while copying 1 page
- * - `WARN_RENAME_PAGE` - Warning page is rename during copy
- * - `WARN_IGNORE_COPY_PERMISSION` - Warning could not copy permission
- * - `WARN_IGNORE_COPY_ATTACHMENT` - Warning could not copy attachment
- * - `WARN_IGNORE_DELETE_PAGE` - Warning ignoring delete of a non agreed on page
- * - `STATUS_COPIED_PAGES` - Message total pages are copied
- * - `STATUS_COPYING_PAGES` - Message copy pages
- * - `STATUS_RELINK_PAGES` - Message relink pages/attachments
- * - `STATUS_DELETING_PAGES` - Message delete pages
- * - `STATUS_DELETED_PAGES` - Message total pages are deleted
- * - `STATUS_MOVING_PAGES` - Message move pages
- * - `WARN_IGNORE_VIEW_RESTRICTED` - Permission changed - view restricted
- * - `WARN_IGNORE_EDIT_RESTRICTED` - Permission changed - edit restricted
- * - `INITIALIZING_TASK` - Message when initializing task
- * - `UNKNOWN_STATUS` - Message when status is unknown
- */
-export interface LongTaskStatus {
-  id: string;
-  name: {
-    key: string;
-    args: {}[];
-  };
-  elapsedTime: number;
-  percentageComplete: number;
-  successful: boolean;
-  messages: Message[];
-  status?: string;
-  errors?: Message[];
-  additionalDetails?: {};
-}
diff --git a/src/api/models/longTaskStatusArray.ts b/src/api/models/longTaskStatusArray.ts
deleted file mode 100644
index 5092f161..00000000
--- a/src/api/models/longTaskStatusArray.ts
+++ /dev/null
@@ -1,10 +0,0 @@
-import type { GenericLinks } from './genericLinks';
-import type { LongTaskStatus } from './longTaskStatus';
-
-export interface LongTaskStatusArray {
-  results: LongTaskStatus[];
-  start: number;
-  limit: number;
-  size: number;
-  _links: GenericLinks;
-}
diff --git a/src/api/models/longTaskStatusWithLinks.ts b/src/api/models/longTaskStatusWithLinks.ts
deleted file mode 100644
index 5b7caf61..00000000
--- a/src/api/models/longTaskStatusWithLinks.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-/* eslint-disable @typescript-eslint/no-explicit-any */
-import type { LongTaskStatus } from './longTaskStatus';
-
-/** Same as LongTaskStatus but with `_links` property. */
-export interface LongTaskStatusWithLinks extends LongTaskStatus {
-  _links: Record;
-}
diff --git a/src/api/models/lookAndFeel.ts b/src/api/models/lookAndFeel.ts
deleted file mode 100644
index 39db065b..00000000
--- a/src/api/models/lookAndFeel.ts
+++ /dev/null
@@ -1,21 +0,0 @@
-import type { ContentLookAndFeel } from './contentLookAndFeel';
-import type { HeaderLookAndFeel } from './headerLookAndFeel';
-import type { HorizontalHeaderLookAndFeel } from './horizontalHeaderLookAndFeel';
-import type { MenusLookAndFeel } from './menusLookAndFeel';
-
-export interface LookAndFeel {
-  headings: {
-    color: string;
-  };
-  links: {
-    color: string;
-  };
-  menus: MenusLookAndFeel;
-  header: HeaderLookAndFeel;
-  content: ContentLookAndFeel;
-  bordersAndDividers: {
-    color: string;
-  };
-  horizontalHeader?: HorizontalHeaderLookAndFeel;
-  spaceReference?: unknown;
-}
diff --git a/src/api/models/lookAndFeelSelection.ts b/src/api/models/lookAndFeelSelection.ts
deleted file mode 100644
index 4af7130c..00000000
--- a/src/api/models/lookAndFeelSelection.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-/** Look and feel selection */
-export interface LookAndFeelSelection {
-  /** The key of the space for which the look and feel settings will be set. */
-  spaceKey: string;
-  lookAndFeelType: string;
-}
diff --git a/src/api/models/lookAndFeelSettings.ts b/src/api/models/lookAndFeelSettings.ts
deleted file mode 100644
index f67895c0..00000000
--- a/src/api/models/lookAndFeelSettings.ts
+++ /dev/null
@@ -1,8 +0,0 @@
-import type { LookAndFeel } from './lookAndFeel';
-
-export interface LookAndFeelSettings {
-  selected: string;
-  global: LookAndFeel;
-  theme?: LookAndFeel;
-  custom: LookAndFeel;
-}
diff --git a/src/api/models/macroInstance.ts b/src/api/models/macroInstance.ts
deleted file mode 100644
index 171f0230..00000000
--- a/src/api/models/macroInstance.ts
+++ /dev/null
@@ -1,8 +0,0 @@
-import type { GenericLinks } from './genericLinks';
-
-export interface MacroInstance {
-  name?: string;
-  body?: string;
-  parameters?: {};
-  _links?: GenericLinks;
-}
diff --git a/src/api/models/menusLookAndFeel.ts b/src/api/models/menusLookAndFeel.ts
deleted file mode 100644
index a0da75bb..00000000
--- a/src/api/models/menusLookAndFeel.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-export interface MenusLookAndFeel {
-  hoverOrFocus: {
-    backgroundColor: string;
-  };
-  color: string;
-}
diff --git a/src/api/models/message.ts b/src/api/models/message.ts
deleted file mode 100644
index 92e67eb3..00000000
--- a/src/api/models/message.ts
+++ /dev/null
@@ -1,5 +0,0 @@
-/* eslint-disable @typescript-eslint/no-explicit-any */
-export interface Message {
-  translation: string;
-  args: Record[];
-}
diff --git a/src/api/models/migratedUser.ts b/src/api/models/migratedUser.ts
deleted file mode 100644
index fca42d8f..00000000
--- a/src/api/models/migratedUser.ts
+++ /dev/null
@@ -1,5 +0,0 @@
-export interface MigratedUser {
-  username?: string;
-  key?: string;
-  accountId?: string;
-}
diff --git a/src/api/models/migratedUserArray.ts b/src/api/models/migratedUserArray.ts
deleted file mode 100644
index 02747c6e..00000000
--- a/src/api/models/migratedUserArray.ts
+++ /dev/null
@@ -1,10 +0,0 @@
-import type { GenericLinks } from './genericLinks';
-import type { MigratedUser } from './migratedUser';
-
-export interface MigratedUserArray {
-  results: MigratedUser[];
-  start: number;
-  limit: number;
-  size: number;
-  _links: GenericLinks;
-}
diff --git a/src/api/models/movePage.ts b/src/api/models/movePage.ts
deleted file mode 100644
index 9a7b5825..00000000
--- a/src/api/models/movePage.ts
+++ /dev/null
@@ -1,3 +0,0 @@
-export interface MovePage {
-  pageId?: string;
-}
diff --git a/src/api/models/navigationLookAndFeel.ts b/src/api/models/navigationLookAndFeel.ts
deleted file mode 100644
index 14fa2a6b..00000000
--- a/src/api/models/navigationLookAndFeel.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-export interface NavigationLookAndFeel {
-  color: string;
-  hoverOrFocus: {
-    backgroundColor: string;
-    color: string;
-  };
-}
diff --git a/src/api/models/operationCheckResult.ts b/src/api/models/operationCheckResult.ts
deleted file mode 100644
index ef859fd0..00000000
--- a/src/api/models/operationCheckResult.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-/** An operation and the target entity that it applies to, e.g. create page. */
-export interface OperationCheckResult {
-  /** The operation itself. */
-  operation: string;
-  /** The space or content type that the operation applies to. */
-  targetType: string;
-}
diff --git a/src/api/models/permissionCheckResponse.ts b/src/api/models/permissionCheckResponse.ts
deleted file mode 100644
index 39563c64..00000000
--- a/src/api/models/permissionCheckResponse.ts
+++ /dev/null
@@ -1,19 +0,0 @@
-import type { Message } from './message';
-
-/**
- * This object represents the response for the content permission check API. If the user or group does not have*
- * permissions, the following errors may be returned:
- *
- * - Group does not have permission to the space
- * - Group does not have permission to the content
- * - User is not allowed to use Confluence
- * - User does not have permission to the space
- * - User does not have permission to the content
- * - Anonymous users are not allowed to use Confluence
- * - Anonymous user does not have permission to the space
- * - Anonymous user does not have permission to the content
- */
-export interface PermissionCheckResponse {
-  hasPermission: boolean;
-  errors?: Message[];
-}
diff --git a/src/api/models/permissionSubject.ts b/src/api/models/permissionSubject.ts
deleted file mode 100644
index 7f412f63..00000000
--- a/src/api/models/permissionSubject.ts
+++ /dev/null
@@ -1,10 +0,0 @@
-/** The user or group that the permission applies to. */
-export interface PermissionSubject {
-  type: string;
-  /**
-   * For `type=user`, identifier should be user's accountId or `anonymous` for anonymous users
-   *
-   * For `type=group`, identifier should be name of the group or groupId
-   */
-  identifier: string;
-}
diff --git a/src/api/models/permissionSubjectWithGroupId.ts b/src/api/models/permissionSubjectWithGroupId.ts
deleted file mode 100644
index 788ef239..00000000
--- a/src/api/models/permissionSubjectWithGroupId.ts
+++ /dev/null
@@ -1,10 +0,0 @@
-/** The user or group that the permission applies to. */
-export interface PermissionSubjectWithGroupId {
-  type: string;
-  /**
-   * For `type=user`, identifier should be user's accountId or `anonymous` for anonymous users
-   *
-   * For `type=group`, identifier should be ID of the group
-   */
-  identifier: string;
-}
diff --git a/src/api/models/propertyValue.ts b/src/api/models/propertyValue.ts
deleted file mode 100644
index 5bfd6144..00000000
--- a/src/api/models/propertyValue.ts
+++ /dev/null
@@ -1,11 +0,0 @@
-/* eslint-disable @typescript-eslint/no-explicit-any */
-/**
- * The value of the property. This can be empty or a complex object.* For example,
- *
- *     "value": {
- *       "example1": "value",
- *       "example2": true,
- *       "example3": 123
- *     }
- */
-export type PropertyValue = Record;
diff --git a/src/api/models/relation.ts b/src/api/models/relation.ts
deleted file mode 100644
index a90de33c..00000000
--- a/src/api/models/relation.ts
+++ /dev/null
@@ -1,15 +0,0 @@
-import type { GenericLinks } from './genericLinks';
-import type { RelationData } from './relationData';
-
-export interface Relation {
-  name: string;
-  relationData?: RelationData;
-  source?: {};
-  target?: {};
-  _expandable: {
-    relationData: string;
-    source: string;
-    target: string;
-  };
-  _links: GenericLinks;
-}
diff --git a/src/api/models/relationArray.ts b/src/api/models/relationArray.ts
deleted file mode 100644
index b29d540a..00000000
--- a/src/api/models/relationArray.ts
+++ /dev/null
@@ -1,10 +0,0 @@
-import type { GenericLinks } from './genericLinks';
-import type { Relation } from './relation';
-
-export interface RelationArray {
-  results: Relation[];
-  start: number;
-  limit: number;
-  size: number;
-  _links: GenericLinks;
-}
diff --git a/src/api/models/relationData.ts b/src/api/models/relationData.ts
deleted file mode 100644
index a6a7ea61..00000000
--- a/src/api/models/relationData.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-import type { User } from './user';
-
-export interface RelationData {
-  createdBy?: User;
-  createdDate?: string;
-  friendlyCreatedDate?: string;
-}
diff --git a/src/api/models/retentionPeriod.ts b/src/api/models/retentionPeriod.ts
deleted file mode 100644
index 342f2e86..00000000
--- a/src/api/models/retentionPeriod.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-export interface RetentionPeriod {
-  /** The number of units for the retention period. */
-  number: number;
-  /** The unit of time that the retention period is measured in. */
-  units: string;
-}
diff --git a/src/api/models/screenLookAndFeel.ts b/src/api/models/screenLookAndFeel.ts
deleted file mode 100644
index 95e84c47..00000000
--- a/src/api/models/screenLookAndFeel.ts
+++ /dev/null
@@ -1,10 +0,0 @@
-export interface ScreenLookAndFeel {
-  background: string;
-  backgroundColor: string;
-  backgroundImage: string;
-  backgroundSize: string;
-  gutterTop: string;
-  gutterRight: string;
-  gutterBottom: string;
-  gutterLeft: string;
-}
diff --git a/src/api/models/searchFieldLookAndFeel.ts b/src/api/models/searchFieldLookAndFeel.ts
deleted file mode 100644
index eae1baff..00000000
--- a/src/api/models/searchFieldLookAndFeel.ts
+++ /dev/null
@@ -1,4 +0,0 @@
-export interface SearchFieldLookAndFeel {
-  backgroundColor: string;
-  color: string;
-}
diff --git a/src/api/models/searchPageResponseSearchResult.ts b/src/api/models/searchPageResponseSearchResult.ts
deleted file mode 100644
index e50bacb1..00000000
--- a/src/api/models/searchPageResponseSearchResult.ts
+++ /dev/null
@@ -1,13 +0,0 @@
-import type { GenericLinks } from './genericLinks';
-import type { SearchResult } from './searchResult';
-
-export interface SearchPageResponseSearchResult {
-  results: SearchResult[];
-  start: number;
-  limit: number;
-  size: number;
-  totalSize: number;
-  cqlQuery: string;
-  searchDuration: number;
-  _links: GenericLinks;
-}
diff --git a/src/api/models/searchResult.ts b/src/api/models/searchResult.ts
deleted file mode 100644
index fc4dea9f..00000000
--- a/src/api/models/searchResult.ts
+++ /dev/null
@@ -1,17 +0,0 @@
-import type { Breadcrumb } from './breadcrumb';
-import type { ContainerSummary } from './containerSummary';
-import type { Content } from './content';
-
-export interface SearchResult {
-  content: Content;
-  title: string;
-  excerpt: string;
-  url: string;
-  resultParentContainer: ContainerSummary;
-  resultGlobalContainer: ContainerSummary;
-  breadcrumbs: Breadcrumb[];
-  entityType: string;
-  iconCssClass: string;
-  lastModified: string;
-  friendlyLastModified: string;
-}
diff --git a/src/api/models/space.ts b/src/api/models/space.ts
deleted file mode 100644
index 7b375aec..00000000
--- a/src/api/models/space.ts
+++ /dev/null
@@ -1,48 +0,0 @@
-import type { Content } from './content';
-import type { GenericLinks } from './genericLinks';
-import type { Icon } from './icon';
-import type { LabelArray } from './labelArray';
-import type { LookAndFeel } from './lookAndFeel';
-import type { OperationCheckResult } from './operationCheckResult';
-import type { SpaceDescription } from './spaceDescription';
-import type { SpacePermission } from './spacePermission';
-import type { SpaceSettings } from './spaceSettings';
-import type { Theme } from './theme';
-
-export interface Space {
-  id: number;
-  key: string;
-  name: string;
-  icon?: Icon;
-  description?: {
-    plain?: SpaceDescription;
-    view?: SpaceDescription;
-  };
-  homepage?: Content;
-  type: string;
-  metadata?: {
-    labels: LabelArray;
-  };
-  operations?: OperationCheckResult[];
-  permissions?: SpacePermission[];
-  status: string;
-  settings?: SpaceSettings;
-  theme?: Theme;
-  lookAndFeel?: LookAndFeel;
-  history?: {
-    createdDate: string;
-  };
-  _expandable: {
-    settings?: string;
-    metadata?: string;
-    operations?: string;
-    lookAndFeel?: string;
-    permissions?: string;
-    icon?: string;
-    description?: string;
-    theme?: string;
-    history?: string;
-    homepage?: string;
-  };
-  _links: GenericLinks;
-}
diff --git a/src/api/models/spaceArray.ts b/src/api/models/spaceArray.ts
deleted file mode 100644
index de011c88..00000000
--- a/src/api/models/spaceArray.ts
+++ /dev/null
@@ -1,10 +0,0 @@
-import type { GenericLinks } from './genericLinks';
-import type { Space } from './space';
-
-export interface SpaceArray {
-  results: Space[];
-  start: number;
-  limit: number;
-  size: number;
-  _links: GenericLinks;
-}
diff --git a/src/api/models/spaceCreate.ts b/src/api/models/spaceCreate.ts
deleted file mode 100644
index 1dd2274d..00000000
--- a/src/api/models/spaceCreate.ts
+++ /dev/null
@@ -1,28 +0,0 @@
-import type { SpaceDescriptionCreate } from './spaceDescriptionCreate';
-import type { SpacePermission } from './spacePermission';
-
-/** This is the request object used when creating a new space. */
-export interface SpaceCreate {
-  /** The name of the new space. */
-  name: string;
-  /**
-   * The key for the new space. Format: See [Space keys](https://confluence.atlassian.com/x/lqNMMQ). If `alias` is not
-   * provided, this is required.
-   */
-  key?: string;
-  /**
-   * This field will be used as the new identifier for the space in confluence page URLs. If the property is not
-   * provided the alias will be the provided key. This property is experimental and may be changed or removed in the
-   * future.
-   */
-  alias?: string;
-  description?: SpaceDescriptionCreate;
-  /**
-   * The permissions for the new space. If no permissions are provided, the [Confluence default space
-   * permissions](https://confluence.atlassian.com/x/UAgzKw#CreateaSpace-Spacepermissions) are applied. Note that if
-   * permissions are provided, the space is created with only the provided set of permissions, not including the default
-   * space permissions. Space permissions can be modified after creation using the space permissions endpoints, and a
-   * private space can be created using the create private space endpoint.
-   */
-  permissions?: SpacePermission[];
-}
diff --git a/src/api/models/spaceDescription.ts b/src/api/models/spaceDescription.ts
deleted file mode 100644
index ddb18a82..00000000
--- a/src/api/models/spaceDescription.ts
+++ /dev/null
@@ -1,5 +0,0 @@
-export interface SpaceDescription {
-  value: string;
-  representation: string;
-  embeddedContent: {}[];
-}
diff --git a/src/api/models/spaceDescriptionCreate.ts b/src/api/models/spaceDescriptionCreate.ts
deleted file mode 100644
index 27061076..00000000
--- a/src/api/models/spaceDescriptionCreate.ts
+++ /dev/null
@@ -1,12 +0,0 @@
-/**
- * The description of the new/updated space. Note, only the 'plain' representation* can be used for the description when
- * creating or updating a space.
- */
-export interface SpaceDescriptionCreate {
-  plain: {
-    /** The space description. */
-    value?: string;
-    /** Set to 'plain'. */
-    representation?: string;
-  };
-}
diff --git a/src/api/models/spacePermission.ts b/src/api/models/spacePermission.ts
deleted file mode 100644
index 58e85f35..00000000
--- a/src/api/models/spacePermission.ts
+++ /dev/null
@@ -1,38 +0,0 @@
-import type { Group } from './group';
-import type { OperationCheckResult } from './operationCheckResult';
-import type { User } from './user';
-
-/**
- * This object represents a permission for given space. Permissions consist of* at least one operation object with an
- * accompanying subjects object.
- *
- * The following combinations of `operation` and `targetType` values are valid for the `operation` object:
- *
- * - 'create': 'page', 'blogpost', 'comment', 'attachment'
- * - 'read': 'space'
- * - 'delete': 'page', 'blogpost', 'comment', 'attachment'
- * - 'export': 'space'
- * - 'administer': 'space'
- */
-export interface SpacePermission {
-  /** The users and/or groups that the permission applies to. */
-  subjects: {
-    user?: {
-      results: User[];
-      size: number;
-    };
-    group?: {
-      results: Group[];
-      size: number;
-    };
-    _expandable: {
-      user?: string;
-      group?: string;
-    };
-  };
-  operation: OperationCheckResult;
-  /** Grant anonymous users permission to use the operation. */
-  anonymousAccess: boolean;
-  /** Grants access to unlicensed users from JIRA Service Desk when used with the 'read space' operation. */
-  unlicensedAccess: boolean;
-}
diff --git a/src/api/models/spacePermissionCreate.ts b/src/api/models/spacePermissionCreate.ts
deleted file mode 100644
index c94d8591..00000000
--- a/src/api/models/spacePermissionCreate.ts
+++ /dev/null
@@ -1,34 +0,0 @@
-import type { GroupCreate } from './groupCreate';
-import type { OperationCheckResult } from './operationCheckResult';
-import type { User } from './user';
-
-/**
- * This object represents a permission for given space. Permissions consist of* at least one operation object with an
- * accompanying subjects object.
- *
- * The following combinations of `operation` and `targetType` values are valid for the `operation` object:
- *
- * - 'create': 'page', 'blogpost', 'comment', 'attachment'
- * - 'read': 'space'
- * - 'delete': 'page', 'blogpost', 'comment', 'attachment'
- * - 'export': 'space'
- * - 'administer': 'space'
- */
-export interface SpacePermissionCreate {
-  /** The users and/or groups that the permission applies to. */
-  subjects: {
-    user?: {
-      results: User[];
-      size: number;
-    };
-    group?: {
-      results: GroupCreate[];
-      size: number;
-    };
-  };
-  operation: OperationCheckResult;
-  /** Grant anonymous users permission to use the operation. */
-  anonymousAccess: boolean;
-  /** Grants access to unlicensed users from JIRA Service Desk when used with the 'read space' operation. */
-  unlicensedAccess: boolean;
-}
diff --git a/src/api/models/spacePermissionCustomContent.ts b/src/api/models/spacePermissionCustomContent.ts
deleted file mode 100644
index 60835ae1..00000000
--- a/src/api/models/spacePermissionCustomContent.ts
+++ /dev/null
@@ -1,17 +0,0 @@
-import type { PermissionSubject } from './permissionSubject';
-
-/**
- * This object represents a list of space permissions for custom content type for an individual user. Permissions
- * consist of* a subjects object and a list with at least one operation object.
- */
-export interface SpacePermissionCustomContent {
-  subject: PermissionSubject;
-  operations: {
-    /** The operation type */
-    key: string;
-    /** The custom content type */
-    target: string;
-    /** Grant or restrict access */
-    access: boolean;
-  }[];
-}
diff --git a/src/api/models/spacePermissionRequest.ts b/src/api/models/spacePermissionRequest.ts
deleted file mode 100644
index a2a7e3e2..00000000
--- a/src/api/models/spacePermissionRequest.ts
+++ /dev/null
@@ -1,42 +0,0 @@
-import type { GenericLinks } from './genericLinks';
-import type { PermissionSubject } from './permissionSubject';
-
-/**
- * This object represents the request for the single space permission. Permissions consist of* at least one operation
- * object with an accompanying subjects object.
- *
- * The following combinations of `operation.key` and `operation.target` values are valid for the `operation` object:
- *
- * ```bash
- * 'create': 'page', 'blogpost', 'comment', 'attachment'
- * 'read': 'space'
- * 'delete': 'page', 'blogpost', 'comment', 'attachment', 'space'
- * 'export': 'space'
- * 'administer': 'space'
- * 'archive': 'page'
- * 'restrict_content': 'space'
- * ```
- *
- * For example, to enable Delete Own permission, set the `operation` object to the following:
- *
- *     "operation": {
- *         "key": "delete",
- *         "target": "space"
- *     }
- *
- * To enable Add/Delete Restrictions permissions, set the `operation` object to the following:
- *
- *     "operation": {
- *         "key": "restrict_content",
- *         "target": "space"
- *     }
- */
-export interface SpacePermissionRequest {
-  subject: PermissionSubject;
-  operation: {
-    key: string;
-    /** The space or content type that the operation applies to. */
-    target: string;
-  };
-  links?: GenericLinks;
-}
diff --git a/src/api/models/spacePermissionV2.ts b/src/api/models/spacePermissionV2.ts
deleted file mode 100644
index a822197a..00000000
--- a/src/api/models/spacePermissionV2.ts
+++ /dev/null
@@ -1,27 +0,0 @@
-import type { GenericLinks } from './genericLinks';
-import type { PermissionSubject } from './permissionSubject';
-
-/**
- * This object represents a single space permission. Permissions consist of* at least one operation object with an
- * accompanying subjects object.
- *
- * The following combinations of `operation.key` and `operation.target` values are valid for the `operation` object:
- *
- * ```bash
- * 'create': 'page', 'blogpost', 'comment', 'attachment'
- * 'read': 'space'
- * 'delete': 'page', 'blogpost', 'comment', 'attachment'
- * 'export': 'space'
- * 'administer': 'space'
- * ```
- */
-export interface SpacePermissionV2 {
-  id?: number;
-  subject: PermissionSubject;
-  operation: {
-    key: string;
-    /** The space or content type that the operation applies to. */
-    target: string;
-  };
-  _links?: GenericLinks;
-}
diff --git a/src/api/models/spacePrivateCreate.ts b/src/api/models/spacePrivateCreate.ts
deleted file mode 100644
index 700e859d..00000000
--- a/src/api/models/spacePrivateCreate.ts
+++ /dev/null
@@ -1,28 +0,0 @@
-import type { SpaceDescriptionCreate } from './spaceDescriptionCreate';
-import type { SpacePermissionCreate } from './spacePermissionCreate';
-
-/** This is the request object used when creating a new private space. */
-export interface SpacePrivateCreate {
-  /** The name of the new space. */
-  name: string;
-  /**
-   * The key for the new space. Format: See [Space keys](https://confluence.atlassian.com/x/lqNMMQ). If `alias` is not
-   * provided, this is required.
-   */
-  key?: string;
-  /**
-   * This field will be used as the new identifier for the space in confluence page URLs. If the property is not
-   * provided the alias will be the provided key. This property is experimental and may be changed or removed in the
-   * future.
-   */
-  alias?: string;
-  description?: SpaceDescriptionCreate;
-  /**
-   * The permissions for the new space. If no permissions are provided, the [Confluence default space
-   * permissions](https://confluence.atlassian.com/x/UAgzKw#CreateaSpace-Spacepermissions) are applied. Note that if
-   * permissions are provided, the space is created with only the provided set of permissions, not including the default
-   * space permissions. Space permissions can be modified after creation using the space permissions endpoints, and a
-   * private space can be created using the create private space endpoint.
-   */
-  permissions?: SpacePermissionCreate[];
-}
diff --git a/src/api/models/spaceProperty.ts b/src/api/models/spaceProperty.ts
deleted file mode 100644
index 02da40ae..00000000
--- a/src/api/models/spaceProperty.ts
+++ /dev/null
@@ -1,18 +0,0 @@
-import type { Space } from './space';
-
-export interface SpaceProperty {
-  id: number;
-  key: string;
-  value: {};
-  version?: {
-    when: string;
-    message: string;
-    number: number;
-    minorEdit: boolean;
-  };
-  space?: Space;
-  _expandable: {
-    version?: string;
-    space?: string;
-  };
-}
diff --git a/src/api/models/spacePropertyArray.ts b/src/api/models/spacePropertyArray.ts
deleted file mode 100644
index 5a9a1986..00000000
--- a/src/api/models/spacePropertyArray.ts
+++ /dev/null
@@ -1,10 +0,0 @@
-import type { GenericLinks } from './genericLinks';
-import type { SpaceProperty } from './spaceProperty';
-
-export interface SpacePropertyArray {
-  results: SpaceProperty[];
-  start: number;
-  limit: number;
-  size: number;
-  _links: GenericLinks;
-}
diff --git a/src/api/models/spacePropertyCreate.ts b/src/api/models/spacePropertyCreate.ts
deleted file mode 100644
index c2a78732..00000000
--- a/src/api/models/spacePropertyCreate.ts
+++ /dev/null
@@ -1,11 +0,0 @@
-import type { PropertyValue } from './propertyValue';
-
-export interface SpacePropertyCreate {
-  /** The key of the new property. */
-  key: string;
-  value: PropertyValue;
-  space?: {
-    /** The key of the space */
-    key?: string;
-  };
-}
diff --git a/src/api/models/spacePropertyCreateNoKey.ts b/src/api/models/spacePropertyCreateNoKey.ts
deleted file mode 100644
index 27cace92..00000000
--- a/src/api/models/spacePropertyCreateNoKey.ts
+++ /dev/null
@@ -1,5 +0,0 @@
-import type { PropertyValue } from './propertyValue';
-
-export interface SpacePropertyCreateNoKey {
-  value: PropertyValue;
-}
diff --git a/src/api/models/spacePropertyUpdate.ts b/src/api/models/spacePropertyUpdate.ts
deleted file mode 100644
index 76be6128..00000000
--- a/src/api/models/spacePropertyUpdate.ts
+++ /dev/null
@@ -1,15 +0,0 @@
-/* eslint-disable @typescript-eslint/no-explicit-any */
-export interface SpacePropertyUpdate {
-  /** The value of the property. */
-  value: Record;
-  /** The version number of the property. */
-  version: {
-    /**
-     * The new version for the updated space property. Set this to the current version number incremented by one. To get
-     * the current version number, use 'Get space property' and retrieve `version.number`.
-     */
-    number: number;
-    /** If `minorEdit` is set to 'true', no notification email or activity stream will be generated for the change. */
-    minorEdit?: boolean;
-  };
-}
diff --git a/src/api/models/spaceSettings.ts b/src/api/models/spaceSettings.ts
deleted file mode 100644
index 9171385f..00000000
--- a/src/api/models/spaceSettings.ts
+++ /dev/null
@@ -1,12 +0,0 @@
-import type { GenericLinks } from './genericLinks';
-
-export interface SpaceSettings {
-  /**
-   * Defines whether an override for the space home should be used. This is used in conjunction with a space theme
-   * provided by an app. For example, if this property is set to true, a theme can display a page other than the space
-   * homepage when users visit the root URL for a space. This property allows apps to provide content-only theming
-   * without overriding the space home.
-   */
-  routeOverrideEnabled: boolean;
-  _links: GenericLinks;
-}
diff --git a/src/api/models/spaceSettingsUpdate.ts b/src/api/models/spaceSettingsUpdate.ts
deleted file mode 100644
index bf8b7a15..00000000
--- a/src/api/models/spaceSettingsUpdate.ts
+++ /dev/null
@@ -1,9 +0,0 @@
-export interface SpaceSettingsUpdate {
-  /**
-   * Defines whether an override for the space home should be used. This is used in conjunction with a space theme
-   * provided by an app. For example, if this property is set to true, a theme can display a page other than the space
-   * homepage when users visit the root URL for a space. This property allows apps to provide content-only theming
-   * without overriding the space home.
-   */
-  routeOverrideEnabled?: boolean;
-}
diff --git a/src/api/models/spaceUpdate.ts b/src/api/models/spaceUpdate.ts
deleted file mode 100644
index 5149077b..00000000
--- a/src/api/models/spaceUpdate.ts
+++ /dev/null
@@ -1,16 +0,0 @@
-import type { SpaceDescriptionCreate } from './spaceDescriptionCreate';
-
-export interface SpaceUpdate {
-  /** The name of the space. */
-  name?: string;
-  description?: SpaceDescriptionCreate;
-  /** The page to set as the homepage of the space. */
-  homepage?: {
-    /** The ID of the page. */
-    id: string;
-  };
-  /** The updated type for this space. */
-  type?: string;
-  /** The updated status for this space. */
-  status?: string;
-}
diff --git a/src/api/models/spaceWatch.ts b/src/api/models/spaceWatch.ts
deleted file mode 100644
index b86fb418..00000000
--- a/src/api/models/spaceWatch.ts
+++ /dev/null
@@ -1,8 +0,0 @@
-import type { SpaceWatchUser } from './spaceWatchUser';
-
-export interface SpaceWatch {
-  type: string;
-  watcher: SpaceWatchUser;
-  contentId?: string;
-  spaceKey: string;
-}
diff --git a/src/api/models/spaceWatchArray.ts b/src/api/models/spaceWatchArray.ts
deleted file mode 100644
index 264dd7c0..00000000
--- a/src/api/models/spaceWatchArray.ts
+++ /dev/null
@@ -1,10 +0,0 @@
-import type { GenericLinks } from './genericLinks';
-import type { SpaceWatch } from './spaceWatch';
-
-export interface SpaceWatchArray {
-  results: SpaceWatch[];
-  start: number;
-  limit: number;
-  size: number;
-  _links?: GenericLinks;
-}
diff --git a/src/api/models/spaceWatchUser.ts b/src/api/models/spaceWatchUser.ts
deleted file mode 100644
index d8a624ca..00000000
--- a/src/api/models/spaceWatchUser.ts
+++ /dev/null
@@ -1,31 +0,0 @@
-import type { Icon } from './icon';
-import type { OperationCheckResult } from './operationCheckResult';
-
-/**
- * This essentially the same as the `User` object, but no `_links` property and* no `_expandable` property (therefore,
- * different required fields).
- */
-export interface SpaceWatchUser {
-  type: string;
-  /**
-   * This property is no longer available and will be removed from the documentation soon. Use `accountId` instead. See
-   * the [deprecation notice](/cloud/confluence/deprecation-notice-user-privacy-api-migration-guide/) for details.
-   */
-  username?: string;
-  /**
-   * This property is no longer available and will be removed from the documentation soon. Use `accountId` instead. See
-   * the [deprecation notice](/cloud/confluence/deprecation-notice-user-privacy-api-migration-guide/) for details.
-   */
-  userKey?: string;
-  /**
-   * The account ID of the user, which uniquely identifies the user across all Atlassian products. For example,
-   * `384093:32b4d9w0-f6a5-3535-11a3-9c8c88d10192`.
-   */
-  accountId: string;
-  profilePicture: Icon;
-  displayName: string;
-  operations?: OperationCheckResult[];
-  accountType: string;
-  email: string;
-  publicName: string;
-}
diff --git a/src/api/models/superBatchWebResources.ts b/src/api/models/superBatchWebResources.ts
deleted file mode 100644
index 7908622d..00000000
--- a/src/api/models/superBatchWebResources.ts
+++ /dev/null
@@ -1,14 +0,0 @@
-export interface SuperBatchWebResources {
-  uris?: {
-    all?: string;
-    css?: string;
-    js?: string;
-  };
-  tags?: {
-    all?: string;
-    css?: string;
-    data?: string;
-    js?: string;
-  };
-  metatags?: string;
-}
diff --git a/src/api/models/systemInfoEntity.ts b/src/api/models/systemInfoEntity.ts
deleted file mode 100644
index b79f1e80..00000000
--- a/src/api/models/systemInfoEntity.ts
+++ /dev/null
@@ -1,8 +0,0 @@
-export interface SystemInfoEntity {
-  cloudId: string;
-  commitHash: string;
-  baseUrl?: string;
-  edition?: string;
-  siteTitle?: string;
-  defaultLocale?: string;
-}
diff --git a/src/api/models/task.ts b/src/api/models/task.ts
deleted file mode 100644
index f25df693..00000000
--- a/src/api/models/task.ts
+++ /dev/null
@@ -1,16 +0,0 @@
-export interface Task {
-  globalId: number;
-  id: number;
-  contentId: number;
-  status: string;
-  title?: string;
-  description?: string;
-  body?: string;
-  creator: string;
-  assignee?: string;
-  completeUser?: string;
-  createDate: number;
-  dueDate?: number;
-  updateDate?: number;
-  completeDate?: number;
-}
diff --git a/src/api/models/taskPageResponse.ts b/src/api/models/taskPageResponse.ts
deleted file mode 100644
index 66cdf250..00000000
--- a/src/api/models/taskPageResponse.ts
+++ /dev/null
@@ -1,8 +0,0 @@
-import type { Task } from './task';
-
-export interface TaskPageResponse {
-  results: Task[];
-  start: number;
-  limit: number;
-  size: number;
-}
diff --git a/src/api/models/taskStatusUpdate.ts b/src/api/models/taskStatusUpdate.ts
deleted file mode 100644
index 1178e6d5..00000000
--- a/src/api/models/taskStatusUpdate.ts
+++ /dev/null
@@ -1,3 +0,0 @@
-export interface TaskStatusUpdate {
-  status: string;
-}
diff --git a/src/api/models/theme.ts b/src/api/models/theme.ts
deleted file mode 100644
index fdefc1cb..00000000
--- a/src/api/models/theme.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-/* eslint-disable @typescript-eslint/no-explicit-any */
-import type { ThemeNoLinks } from './themeNoLinks';
-
-export interface Theme extends ThemeNoLinks {
-  _links: Record;
-}
diff --git a/src/api/models/themeArray.ts b/src/api/models/themeArray.ts
deleted file mode 100644
index b1c141e3..00000000
--- a/src/api/models/themeArray.ts
+++ /dev/null
@@ -1,10 +0,0 @@
-import type { GenericLinks } from './genericLinks';
-import type { ThemeNoLinks } from './themeNoLinks';
-
-export interface ThemeArray {
-  results: ThemeNoLinks[];
-  start: number;
-  limit: number;
-  size: number;
-  _links: GenericLinks;
-}
diff --git a/src/api/models/themeNoLinks.ts b/src/api/models/themeNoLinks.ts
deleted file mode 100644
index fdd2bd8c..00000000
--- a/src/api/models/themeNoLinks.ts
+++ /dev/null
@@ -1,9 +0,0 @@
-import type { Icon } from './icon';
-
-/** Theme object without links. Used in ThemeArray. */
-export interface ThemeNoLinks {
-  themeKey: string;
-  name: string;
-  description: string;
-  icon: Icon;
-}
diff --git a/src/api/models/themeUpdate.ts b/src/api/models/themeUpdate.ts
deleted file mode 100644
index b5988868..00000000
--- a/src/api/models/themeUpdate.ts
+++ /dev/null
@@ -1,4 +0,0 @@
-export interface ThemeUpdate {
-  /** The key of the theme to be set as the space theme. */
-  themeKey: string;
-}
diff --git a/src/api/models/topNavigationLookAndFeel.ts b/src/api/models/topNavigationLookAndFeel.ts
deleted file mode 100644
index 445f13b0..00000000
--- a/src/api/models/topNavigationLookAndFeel.ts
+++ /dev/null
@@ -1,8 +0,0 @@
-export interface TopNavigationLookAndFeel {
-  color?: string;
-  highlightColor: string;
-  hoverOrFocus?: {
-    backgroundColor?: string;
-    color?: string;
-  };
-}
diff --git a/src/api/models/user.ts b/src/api/models/user.ts
deleted file mode 100644
index 27fbef11..00000000
--- a/src/api/models/user.ts
+++ /dev/null
@@ -1,40 +0,0 @@
-import type { GenericLinks } from './genericLinks';
-import type { Icon } from './icon';
-import type { OperationCheckResult } from './operationCheckResult';
-import type { Space } from './space';
-
-export interface User {
-  type: string;
-  /**
-   * This property is no longer available and will be removed from the documentation soon. Use `accountId` instead. See
-   * the [deprecation notice](/cloud/confluence/deprecation-notice-user-privacy-api-migration-guide/) for details.
-   */
-  username?: string;
-  /**
-   * This property is no longer available and will be removed from the documentation soon. Use `accountId` instead. See
-   * the [deprecation notice](/cloud/confluence/deprecation-notice-user-privacy-api-migration-guide/) for details.
-   */
-  userKey?: string;
-  /**
-   * The account ID of the user, which uniquely identifies the user across all Atlassian products. For example,
-   * `384093:32b4d9w0-f6a5-3535-11a3-9c8c88d10192`.
-   */
-  accountId: string;
-  /** The account type of the user, may return empty string if unavailable. */
-  accountType: string;
-  /** The email address of the user. Depending on the user's privacy setting, this may return an empty string. */
-  email: string;
-  /** The public name or nickname of the user. Will always contain a value. */
-  publicName: string;
-  profilePicture: Icon;
-  /** The display name of the user. Depending on the user's privacy setting, this may be the same as publicName. */
-  displayName: string;
-  operations?: OperationCheckResult[];
-  personalSpace?: Space;
-  _expandable: {
-    operations?: string;
-    details?: string;
-    personalSpace?: string;
-  };
-  _links: GenericLinks;
-}
diff --git a/src/api/models/userAnonymous.ts b/src/api/models/userAnonymous.ts
deleted file mode 100644
index 5422f99e..00000000
--- a/src/api/models/userAnonymous.ts
+++ /dev/null
@@ -1,14 +0,0 @@
-import type { GenericLinks } from './genericLinks';
-import type { Icon } from './icon';
-import type { OperationCheckResult } from './operationCheckResult';
-
-export interface UserAnonymous {
-  type: string;
-  profilePicture: Icon;
-  displayName: string;
-  operations?: OperationCheckResult[];
-  _expandable: {
-    operations?: string;
-  };
-  _links: GenericLinks;
-}
diff --git a/src/api/models/userArray.ts b/src/api/models/userArray.ts
deleted file mode 100644
index ba056309..00000000
--- a/src/api/models/userArray.ts
+++ /dev/null
@@ -1,8 +0,0 @@
-import type { User } from './user';
-
-export interface UserArray {
-  results: User[];
-  start: number;
-  limit: number;
-  size: number;
-}
diff --git a/src/api/models/userProperty.ts b/src/api/models/userProperty.ts
deleted file mode 100644
index c941e5c4..00000000
--- a/src/api/models/userProperty.ts
+++ /dev/null
@@ -1,14 +0,0 @@
-import type { GenericLinks } from './genericLinks';
-
-export interface UserProperty {
-  key: string;
-  /** The value of the content property. */
-  value: {};
-  /** A unique identifier for the user property */
-  id: string;
-  /** Datetime when the property was last modified such as `2022-02-01T12:00:00.111Z` */
-  lastModifiedDate: string;
-  /** Datetime when the property was created such as `2022-01-01T12:00:00.111Z` */
-  createdDate: string;
-  Links?: GenericLinks;
-}
diff --git a/src/api/models/userPropertyCreate.ts b/src/api/models/userPropertyCreate.ts
deleted file mode 100644
index bbc64795..00000000
--- a/src/api/models/userPropertyCreate.ts
+++ /dev/null
@@ -1,4 +0,0 @@
-export interface UserPropertyCreate {
-  /** The value of the user property. */
-  value: {};
-}
diff --git a/src/api/models/userPropertyKeyArray.ts b/src/api/models/userPropertyKeyArray.ts
deleted file mode 100644
index 0e4d2322..00000000
--- a/src/api/models/userPropertyKeyArray.ts
+++ /dev/null
@@ -1,11 +0,0 @@
-import type { GenericLinks } from './genericLinks';
-
-export interface UserPropertyKeyArray {
-  results: {
-    key?: string;
-  }[];
-  start?: number;
-  limit?: number;
-  size?: number;
-  Links?: GenericLinks;
-}
diff --git a/src/api/models/userPropertyUpdate.ts b/src/api/models/userPropertyUpdate.ts
deleted file mode 100644
index 0408de76..00000000
--- a/src/api/models/userPropertyUpdate.ts
+++ /dev/null
@@ -1,4 +0,0 @@
-export interface UserPropertyUpdate {
-  /** The value of the user property. */
-  value: {};
-}
diff --git a/src/api/models/userWatch.ts b/src/api/models/userWatch.ts
deleted file mode 100644
index 0c9cbff4..00000000
--- a/src/api/models/userWatch.ts
+++ /dev/null
@@ -1,3 +0,0 @@
-export interface UserWatch {
-  watching: boolean;
-}
diff --git a/src/api/models/usersUserKeys.ts b/src/api/models/usersUserKeys.ts
deleted file mode 100644
index 889458df..00000000
--- a/src/api/models/usersUserKeys.ts
+++ /dev/null
@@ -1,8 +0,0 @@
-import type { GenericLinks } from './genericLinks';
-import type { User } from './user';
-
-export interface UsersUserKeys {
-  users: User[];
-  userKeys: string[];
-  _links?: GenericLinks;
-}
diff --git a/src/api/models/version.ts b/src/api/models/version.ts
deleted file mode 100644
index 012cbad3..00000000
--- a/src/api/models/version.ts
+++ /dev/null
@@ -1,20 +0,0 @@
-import type { Content } from './content';
-import type { GenericLinks } from './genericLinks';
-import type { User } from './user';
-import type { UsersUserKeys } from './usersUserKeys';
-
-export interface Version {
-  by: User;
-  when: string;
-  friendlyWhen: string;
-  message: string;
-  number: number;
-  minorEdit: boolean;
-  content?: Content;
-  collaborators?: UsersUserKeys;
-  _expandable: {
-    content: string;
-    collaborators: string;
-  };
-  _links: GenericLinks;
-}
diff --git a/src/api/models/versionArray.ts b/src/api/models/versionArray.ts
deleted file mode 100644
index 744c19a6..00000000
--- a/src/api/models/versionArray.ts
+++ /dev/null
@@ -1,10 +0,0 @@
-import type { GenericLinks } from './genericLinks';
-import type { Version } from './version';
-
-export interface VersionArray {
-  results: Version[];
-  start: number;
-  limit: number;
-  size: number;
-  _links: GenericLinks;
-}
diff --git a/src/api/models/versionRestore.ts b/src/api/models/versionRestore.ts
deleted file mode 100644
index 0d3c8053..00000000
--- a/src/api/models/versionRestore.ts
+++ /dev/null
@@ -1,10 +0,0 @@
-export interface VersionRestore {
-  /** Set to 'restore'. */
-  operationKey: string;
-  params: {
-    /** The version number to be restored. */
-    versionNumber: number;
-    /** Description for the version. */
-    message: string;
-  };
-}
diff --git a/src/api/models/watch.ts b/src/api/models/watch.ts
deleted file mode 100644
index e7152f31..00000000
--- a/src/api/models/watch.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-import type { WatchUser } from './watchUser';
-
-export interface Watch {
-  type: string;
-  watcher: WatchUser;
-  contentId: string;
-}
diff --git a/src/api/models/watchArray.ts b/src/api/models/watchArray.ts
deleted file mode 100644
index e126202f..00000000
--- a/src/api/models/watchArray.ts
+++ /dev/null
@@ -1,10 +0,0 @@
-import type { GenericLinks } from './genericLinks';
-import type { Watch } from './watch';
-
-export interface WatchArray {
-  results: Watch[];
-  start: number;
-  limit: number;
-  size: number;
-  _links: GenericLinks;
-}
diff --git a/src/api/models/watchUser.ts b/src/api/models/watchUser.ts
deleted file mode 100644
index e24bd04f..00000000
--- a/src/api/models/watchUser.ts
+++ /dev/null
@@ -1,28 +0,0 @@
-import type { Icon } from './icon';
-import type { OperationCheckResult } from './operationCheckResult';
-
-/**
- * This essentially the same as the `User` object, but no `_links` property and* no `_expandable` property (therefore,
- * different required fields).
- */
-export interface WatchUser {
-  type: string;
-  /**
-   * This property is no longer available and will be removed from the documentation soon. Use `accountId` instead. See
-   * the [deprecation notice](/cloud/confluence/deprecation-notice-user-privacy-api-migration-guide/) for details.
-   */
-  username?: string;
-  /**
-   * This property is no longer available and will be removed from the documentation soon. Use `accountId` instead. See
-   * the [deprecation notice](/cloud/confluence/deprecation-notice-user-privacy-api-migration-guide/) for details.
-   */
-  userKey?: string;
-  /**
-   * The account ID of the user, which uniquely identifies the user across all Atlassian products. For example,
-   * `384093:32b4d9w0-f6a5-3535-11a3-9c8c88d10192`.
-   */
-  accountId: string;
-  profilePicture: Icon;
-  displayName: string;
-  operations: OperationCheckResult[];
-}
diff --git a/src/api/models/webResourceDependencies.ts b/src/api/models/webResourceDependencies.ts
deleted file mode 100644
index 1002c4e1..00000000
--- a/src/api/models/webResourceDependencies.ts
+++ /dev/null
@@ -1,18 +0,0 @@
-import type { SuperBatchWebResources } from './superBatchWebResources';
-
-export interface WebResourceDependencies {
-  keys?: string[];
-  contexts?: string[];
-  uris?: {
-    all?: string;
-    css?: string;
-    js?: string;
-  };
-  tags?: {
-    all?: string;
-    css?: string;
-    data?: string;
-    js?: string;
-  };
-  superbatch?: SuperBatchWebResources;
-}
diff --git a/src/api/parameters/addContentWatcher.ts b/src/api/parameters/addContentWatcher.ts
deleted file mode 100644
index a198e446..00000000
--- a/src/api/parameters/addContentWatcher.ts
+++ /dev/null
@@ -1,19 +0,0 @@
-export interface AddContentWatcher {
-  /** The ID of the content to add the watcher to. */
-  contentId: string;
-  /**
-   * This parameter is no longer available and will be removed from the documentation soon. Use `accountId` instead. See
-   * the [deprecation notice](/cloud/confluence/deprecation-notice-user-privacy-api-migration-guide/) for details.
-   */
-  key?: string;
-  /**
-   * This parameter is no longer available and will be removed from the documentation soon. Use `accountId` instead. See
-   * the [deprecation notice](/cloud/confluence/deprecation-notice-user-privacy-api-migration-guide/) for details.
-   */
-  username?: string;
-  /**
-   * The `accountId` of the user to be added as a watcher. The accountId uniquely identifies the user across all
-   * Atlassian products. For example, `384093:32b4d9w0-f6a5-3535-11a3-9c8c88d10192`.
-   */
-  accountId: string;
-}
diff --git a/src/api/parameters/addCustomContentPermissions.ts b/src/api/parameters/addCustomContentPermissions.ts
deleted file mode 100644
index ef8ad8c7..00000000
--- a/src/api/parameters/addCustomContentPermissions.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-import type { SpacePermissionCustomContent } from '../models';
-
-export interface AddCustomContentPermissions extends SpacePermissionCustomContent {
-  /** The key of the space to be queried for its content. */
-  spaceKey: string;
-}
diff --git a/src/api/parameters/addGroupToContentRestriction.ts b/src/api/parameters/addGroupToContentRestriction.ts
deleted file mode 100644
index 313b8df0..00000000
--- a/src/api/parameters/addGroupToContentRestriction.ts
+++ /dev/null
@@ -1,8 +0,0 @@
-export interface AddGroupToContentRestriction {
-  /** The ID of the content that the restriction applies to. */
-  id: string;
-  /** The operation that the restriction applies to. */
-  operationKey: string;
-  /** The name of the group to add to the content restriction. */
-  groupName: string;
-}
diff --git a/src/api/parameters/addGroupToContentRestrictionByGroupId.ts b/src/api/parameters/addGroupToContentRestrictionByGroupId.ts
deleted file mode 100644
index b10e93b5..00000000
--- a/src/api/parameters/addGroupToContentRestrictionByGroupId.ts
+++ /dev/null
@@ -1,8 +0,0 @@
-export interface AddGroupToContentRestrictionByGroupId {
-  /** The ID of the content that the restriction applies to. */
-  id: string;
-  /** The operation that the restriction applies to. */
-  operationKey: string;
-  /** The groupId of the group to add to the content restriction. */
-  groupId: string;
-}
diff --git a/src/api/parameters/addLabelWatcher.ts b/src/api/parameters/addLabelWatcher.ts
deleted file mode 100644
index 1268f819..00000000
--- a/src/api/parameters/addLabelWatcher.ts
+++ /dev/null
@@ -1,21 +0,0 @@
-export interface AddLabelWatcher {
-  /** Note, you must add header when making a request, as this operation has XSRF protection. */
-  'X-Atlassian-Token': string;
-  /** The name of the label to add the watcher to. */
-  labelName: string;
-  /**
-   * This parameter is no longer available and will be removed from the documentation soon. Use `accountId` instead. See
-   * the [deprecation notice](/cloud/confluence/deprecation-notice-user-privacy-api-migration-guide/) for details.
-   */
-  key?: string;
-  /**
-   * This parameter is no longer available and will be removed from the documentation soon. Use `accountId` instead. See
-   * the [deprecation notice](/cloud/confluence/deprecation-notice-user-privacy-api-migration-guide/) for details.
-   */
-  username?: string;
-  /**
-   * The `accountId` of the user to be added as a watcher. The accountId uniquely identifies the user across all
-   * Atlassian products. For example, `384093:32b4d9w0-f6a5-3535-11a3-9c8c88d10192`.
-   */
-  accountId: string;
-}
diff --git a/src/api/parameters/addLabelsToContent.ts b/src/api/parameters/addLabelsToContent.ts
deleted file mode 100644
index a801831a..00000000
--- a/src/api/parameters/addLabelsToContent.ts
+++ /dev/null
@@ -1,17 +0,0 @@
-import type { LabelCreateArray } from '../models';
-
-export interface AddLabelsToContent {
-  /** The ID of the content that will have labels added to it. */
-  id: string;
-  /**
-   * If true, return the new 400 error response on invalid requests. Otherwise return a server error response on invalid
-   * requests.
-   *
-   * Why does this parameter exist? Previously, our API was returning a 500 status code with a difficult-to-consume
-   * response body. We've fixed the response to have a 400 status code and a more useful body. This parameter enables a
-   * smooth transition without a breaking change; eventually, we'll completely remove the 500 response and this
-   * parameter won't be needed.
-   */
-  'use-400-error-response'?: boolean;
-  body: LabelCreateArray;
-}
diff --git a/src/api/parameters/addLabelsToSpace.ts b/src/api/parameters/addLabelsToSpace.ts
deleted file mode 100644
index 0b828390..00000000
--- a/src/api/parameters/addLabelsToSpace.ts
+++ /dev/null
@@ -1,4 +0,0 @@
-export interface AddLabelsToSpace {
-  /** The key of the space to add labels to. */
-  spaceKey: string;
-}
diff --git a/src/api/parameters/addPermissionToSpace.ts b/src/api/parameters/addPermissionToSpace.ts
deleted file mode 100644
index f28b7c13..00000000
--- a/src/api/parameters/addPermissionToSpace.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-import type { SpacePermissionRequest } from '../models';
-
-export interface AddPermissionToSpace extends SpacePermissionRequest {
-  /** The key of the space to be queried for its content. */
-  spaceKey: string;
-}
diff --git a/src/api/parameters/addRestrictions.ts b/src/api/parameters/addRestrictions.ts
deleted file mode 100644
index a651b0a5..00000000
--- a/src/api/parameters/addRestrictions.ts
+++ /dev/null
@@ -1,15 +0,0 @@
-import type { AddContentRestrictionUpdateArray } from '../models';
-
-export interface AddRestrictions {
-  /** The ID of the content to add restrictions to. */
-  id: string;
-  /**
-   * A multi-value parameter indicating which properties of the content restrictions (returned in response) to expand.
-   *
-   * - `restrictions.user` returns the piece of content that the restrictions are applied to. Expanded by default.
-   * - `restrictions.group` returns the piece of content that the restrictions are applied to. Expanded by default.
-   * - `content` returns the piece of content that the restrictions are applied to.
-   */
-  expand?: string[];
-  body: AddContentRestrictionUpdateArray;
-}
diff --git a/src/api/parameters/addSpaceWatcher.ts b/src/api/parameters/addSpaceWatcher.ts
deleted file mode 100644
index 52d769b7..00000000
--- a/src/api/parameters/addSpaceWatcher.ts
+++ /dev/null
@@ -1,21 +0,0 @@
-export interface AddSpaceWatcher {
-  /** Note, you must add header when making a request, as this operation has XSRF protection. */
-  'X-Atlassian-Token': string;
-  /** The key of the space to add the watcher to. */
-  spaceKey: string;
-  /**
-   * This parameter is no longer available and will be removed from the documentation soon. Use `accountId` instead. See
-   * the [deprecation notice](/cloud/confluence/deprecation-notice-user-privacy-api-migration-guide/) for details.
-   */
-  key?: string;
-  /**
-   * This parameter is no longer available and will be removed from the documentation soon. Use `accountId` instead. See
-   * the [deprecation notice](/cloud/confluence/deprecation-notice-user-privacy-api-migration-guide/) for details.
-   */
-  username?: string;
-  /**
-   * The `accountId` of the user to be added as a watcher. The accountId uniquely identifies the user across all
-   * Atlassian products. For example, `384093:32b4d9w0-f6a5-3535-11a3-9c8c88d10192`.
-   */
-  accountId: string;
-}
diff --git a/src/api/parameters/addUserToContentRestriction.ts b/src/api/parameters/addUserToContentRestriction.ts
deleted file mode 100644
index 13ab0b8b..00000000
--- a/src/api/parameters/addUserToContentRestriction.ts
+++ /dev/null
@@ -1,21 +0,0 @@
-export interface AddUserToContentRestriction {
-  /** The ID of the content that the restriction applies to. */
-  id: string;
-  /** The operation that the restriction applies to. */
-  operationKey: string;
-  /**
-   * This parameter is no longer available and will be removed from the documentation soon. Use `accountId` instead. See
-   * the [deprecation notice](/cloud/confluence/deprecation-notice-user-privacy-api-migration-guide/) for details.
-   */
-  key?: string;
-  /**
-   * This parameter is no longer available and will be removed from the documentation soon. Use `accountId` instead. See
-   * the [deprecation notice](/cloud/confluence/deprecation-notice-user-privacy-api-migration-guide/) for details.
-   */
-  userName?: string;
-  /**
-   * The account ID of the user to add to the content restriction. The accountId uniquely identifies the user across all
-   * Atlassian products. For example, `384093:32b4d9w0-f6a5-3535-11a3-9c8c88d10192`.
-   */
-  accountId: string;
-}
diff --git a/src/api/parameters/addUserToGroup.ts b/src/api/parameters/addUserToGroup.ts
deleted file mode 100644
index 6d5652a3..00000000
--- a/src/api/parameters/addUserToGroup.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-import type { AccountId } from '../models';
-
-export interface AddUserToGroup extends AccountId {
-  /** Name of the group whose membership is updated */
-  name: string;
-}
diff --git a/src/api/parameters/addUserToGroupByGroupId.ts b/src/api/parameters/addUserToGroupByGroupId.ts
deleted file mode 100644
index 6e1b761e..00000000
--- a/src/api/parameters/addUserToGroupByGroupId.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-import type { AccountId } from '../models';
-
-export interface AddUserToGroupByGroupId extends AccountId {
-  /** GroupId of the group whose membership is updated */
-  groupId: string;
-}
diff --git a/src/api/parameters/archivePages.ts b/src/api/parameters/archivePages.ts
deleted file mode 100644
index 72624158..00000000
--- a/src/api/parameters/archivePages.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-export interface ArchivePages {
-  pages: Array<{
-    /** The `id` of the page to be archived. */
-    id: number;
-  }>;
-}
diff --git a/src/api/parameters/asyncConvertContentBodyRequest.ts b/src/api/parameters/asyncConvertContentBodyRequest.ts
deleted file mode 100644
index 97d6e4db..00000000
--- a/src/api/parameters/asyncConvertContentBodyRequest.ts
+++ /dev/null
@@ -1,81 +0,0 @@
-import type { ContentBodyCreate } from '../models';
-
-export interface AsyncConvertContentBodyRequest extends ContentBodyCreate {
-  /** The name of the target format for the content body. */
-  to: string;
-  /**
-   * The space key used for resolving embedded content (page includes, files, and links) in the content body. For
-   * example, if the source content contains the link ``
-   * and the `spaceKeyContext=TEST` parameter is provided, then the link will be converted to a link to the "Example
-   * page" page in the "TEST" space.
-   */
-  spaceKeyContext?: string;
-  /**
-   * The content ID used to find the space for resolving embedded content (page includes, files, and links) in the
-   * content body. For example, if the source content contains the link `` and the `contentIdContext=123` parameter is provided, then the link will be converted to a link
-   * to the "Example page" page in the same space that has the content with ID=123. Note, `spaceKeyContext` will be
-   * ignored if this parameter is provided.
-   */
-  contentIdContext?: string;
-  /**
-   * If this field is false, the cache will erase its current value and begin a new conversion. If this field is true,
-   * the cache will not erase its current value, and will set the status of the async conversion to RERUNNING. Once the
-   * data is updated, the status will change to COMPLETED. Large macros that take long to convert, and whose data need
-   * not immediately up to date (same as previous conversion's result within last 5 minutes) should set this fields to
-   * true. Cache values are stored per user per content body and expansions.
-   */
-  allowCache?: boolean;
-  /**
-   * Mode used for rendering embedded content, like attachments.
-   *
-   *     - `current` renders the embedded content using the latest version.
-   *     - `version-at-save` renders the embedded content using the version at
-   *     the time of save.
-   */
-  embeddedContentRender?: string;
-  /** A multi-value parameter indicating which properties of the content to expand and populate. */
-  expand?:
-    | 'embeddedContent'
-    | 'mediaToken'
-    | 'webresource.superbatch.metatags'
-    | 'webresource.superbatch.tags.all'
-    | 'webresource.superbatch.tags.css'
-    | 'webresource.superbatch.tags.data'
-    | 'webresource.superbatch.tags.js'
-    | 'webresource.superbatch.uris.all'
-    | 'webresource.superbatch.uris.css'
-    | 'webresource.superbatch.uris.data'
-    | 'webresource.superbatch.uris.js'
-    | 'webresource.tags.all'
-    | 'webresource.tags.css'
-    | 'webresource.tags.data'
-    | 'webresource.tags.js'
-    | 'webresource.uris.all'
-    | 'webresource.uris.css'
-    | 'webresource.uris.data'
-    | 'webresource.uris.js'
-    | (
-        | 'embeddedContent'
-        | 'mediaToken'
-        | 'webresource.superbatch.metatags'
-        | 'webresource.superbatch.tags.all'
-        | 'webresource.superbatch.tags.css'
-        | 'webresource.superbatch.tags.data'
-        | 'webresource.superbatch.tags.js'
-        | 'webresource.superbatch.uris.all'
-        | 'webresource.superbatch.uris.css'
-        | 'webresource.superbatch.uris.data'
-        | 'webresource.superbatch.uris.js'
-        | 'webresource.tags.all'
-        | 'webresource.tags.css'
-        | 'webresource.tags.data'
-        | 'webresource.tags.js'
-        | 'webresource.uris.all'
-        | 'webresource.uris.css'
-        | 'webresource.uris.data'
-        | 'webresource.uris.js'
-    )[]
-    | string
-    | string[];
-}
diff --git a/src/api/parameters/asyncConvertContentBodyResponse.ts b/src/api/parameters/asyncConvertContentBodyResponse.ts
deleted file mode 100644
index 9192b061..00000000
--- a/src/api/parameters/asyncConvertContentBodyResponse.ts
+++ /dev/null
@@ -1,4 +0,0 @@
-export interface AsyncConvertContentBodyResponse {
-  /** The asyncId of the macro task to get the converted body. */
-  id: string;
-}
diff --git a/src/api/parameters/bulkAsyncConvertContentBodyRequest.ts b/src/api/parameters/bulkAsyncConvertContentBodyRequest.ts
deleted file mode 100644
index adeffae0..00000000
--- a/src/api/parameters/bulkAsyncConvertContentBodyRequest.ts
+++ /dev/null
@@ -1,88 +0,0 @@
-import type { OneOrMany } from '../../interfaces';
-
-export interface BulkAsyncConvertContentBodyRequest {
-  /** The name of the target format for the content body conversion. */
-  to: string;
-  /** This object is used when creating or updating content. */
-  // eslint-disable-next-line @typescript-eslint/no-explicit-any
-  body: Record & {
-    /** The body of the content in the relevant format. */
-    value: string;
-    /** The content format type. Set the value of this property to the name of the format being used, e.g. 'storage'. */
-    representation:
-      | 'view'
-      | 'export_view'
-      | 'styled_view'
-      | 'storage'
-      | 'editor'
-      | 'editor2'
-      | 'anonymous_export_view'
-      | 'wiki'
-      | 'atlas_doc_format'
-      | 'plain'
-      | 'raw'
-      | string;
-  };
-  /**
-   * A multi-value, comma-separated parameter indicating which properties of the content to expand and populate. Expands
-   * are dependent on the `to` conversion format and may be irrelevant for certain conversions (e.g.
-   * `macroRenderedOutput` is redundant when converting to `view` format).
-   *
-   * If rendering to `view` format, and the body content being converted includes arbitrary nested content (such as
-   * macros); then it is necessary to include webresource expands in the request. Webresources for content body are the
-   * batched JS and CSS dependencies for any nested dynamic content (i.e. macros).
-   */
-  expand?: OneOrMany<
-    | 'embeddedContent'
-    | 'mediaToken'
-    | 'macroRenderedOutput'
-    | 'webresource.superbatch.uris.js'
-    | 'webresource.superbatch.uris.css'
-    | 'webresource.superbatch.uris.all'
-    | 'webresource.superbatch.tags.all'
-    | 'webresource.superbatch.tags.css'
-    | 'webresource.superbatch.tags.js'
-    | 'webresource.uris.js'
-    | 'webresource.uris.css'
-    | 'webresource.uris.all'
-    | 'webresource.tags.all'
-    | 'webresource.tags.css'
-    | 'webresource.tags.js'
-  >;
-  /**
-   * Mode used for rendering embedded content, such as attachments.
-   *
-   * - `current` renders the embedded content using the latest version.
-   * - `version-at-save renders` the embedded content using the version at the time of save.
-   *
-   * @default current
-   */
-  embeddedContentRender?: 'current' | 'version-at-save' | string;
-  /**
-   * The content ID used to find the space for resolving embedded content (page includes, files, and links) in the
-   * content body. For example, if the source content contains the link
-   *
-   * `` and the `contentIdContext=123` parameter is
-   * provided, then the link will be converted into a link to the "Example page" page in the same space that has the
-   * content with ID=123. Note that `spaceKeyContext` will be ignored if this parameter is provided.
-   */
-  contentIdContext?: string;
-  /**
-   * The space key used for resolving embedded content (page includes, files, and links) in the content body. For
-   * example, if the source content contains the link ``
-   * and the `spaceKeyContext=TEST` parameter is provided, then the link will be converted into a link to the "Example
-   * page" page in the "TEST" space.
-   */
-  spaceKeyContext?: string;
-  /**
-   * If `false`, the cache will erase its current value and begin a new conversion. If `true`, the cache will not erase
-   * its current value, and will set the status of the async conversion to “RERUNNING”. Once the data is updated, the
-   * status will change to “COMPLETED”. Large macros that take a long time to convert and that need not be immediately
-   * up to date (e.g. a macro in which the new conversion result is the same as a previous conversion result that was
-   * completed within the last 5 minutes) should set this field to `true`. Cache values are stored per user per content
-   * body and expansions.
-   *
-   * @default false
-   */
-  allowCache?: boolean;
-}
diff --git a/src/api/parameters/bulkAsyncConvertContentBodyResponse.ts b/src/api/parameters/bulkAsyncConvertContentBodyResponse.ts
deleted file mode 100644
index 3c443c40..00000000
--- a/src/api/parameters/bulkAsyncConvertContentBodyResponse.ts
+++ /dev/null
@@ -1,4 +0,0 @@
-export interface BulkAsyncConvertContentBodyResponse {
-  /** The asyncIds of the conversion tasks. */
-  ids: string[];
-}
diff --git a/src/api/parameters/checkContentPermission.ts b/src/api/parameters/checkContentPermission.ts
deleted file mode 100644
index 57e1f179..00000000
--- a/src/api/parameters/checkContentPermission.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-import type { ContentPermissionRequest } from '../models';
-
-export interface CheckContentPermission extends ContentPermissionRequest {
-  /** The ID of the content to check permissions against. */
-  id: string;
-}
diff --git a/src/api/parameters/convertContentBody.ts b/src/api/parameters/convertContentBody.ts
deleted file mode 100644
index 3e83135e..00000000
--- a/src/api/parameters/convertContentBody.ts
+++ /dev/null
@@ -1,59 +0,0 @@
-/* eslint-disable @typescript-eslint/no-explicit-any */
-import type { ContentBodyCreate } from '../models';
-import type { OneOrMany } from '~/interfaces';
-
-export interface ConvertContentBody extends ContentBodyCreate {
-  /** The name of the target format for the content body. */
-  to: string;
-
-  /**
-   * A multi-value parameter indicating which properties of the content to expand. Expands are dependent on the to
-   * conversion format and may be irrelevant for certain conversions (e.g. macroRenderedOutput is redundant when
-   * converting to view format).
-   *
-   * - `webresource` returns JS and CSS resources necessary for displaying nested content in `view` format
-   * - `webresource.superbatch.uris.js` returns all common JS dependencies
-   * - `webresource.superbatch.uris.css` returns all common CSS dependencies
-   * - `webresource.uris.js` returns JS dependencies specific to conversion
-   * - `webresource.uris.css` returns CSS dependencies specific to conversion
-   * - `embeddedContent` returns metadata for nested content (e.g. page included using page include macro)
-   * - `mediaToken` returns JWT token for retrieving attachment data from Media API
-   * - `macroRenderedOutput` additionally converts body to view format
-   */
-  expand?: OneOrMany<
-    | 'webresource'
-    | 'webresource.superbatch.uris.js'
-    | 'webresource.superbatch.uris.css'
-    | 'webresource.uris.js'
-    | 'webresource.uris.css'
-    | 'embeddedContent'
-    | 'mediaToken'
-    | 'macroRenderedOutput'
-    | string
-  >;
-
-  /**
-   * The space key used for resolving embedded content (page includes, files, and links) in the content body. For
-   * example, if the source content contains the link ``
-   * and the `spaceKeyContext=TEST` parameter is provided, then the link will be converted to a link to the "Example
-   * page" page in the "TEST" space.
-   */
-  spaceKeyContext?: string;
-  /**
-   * The content ID used to find the space for resolving embedded content (page includes, files, and links) in the
-   * content body. For example, if the source content contains the link `` and the `contentIdContext=123` parameter is provided, then the link will be converted to a link
-   * to the "Example page" page in the same space that has the content with ID=123. Note, `spaceKeyContext` will be
-   * ignored if this parameter is provided.
-   */
-  contentIdContext?: string;
-  /**
-   * Mode used for rendering embedded content, like attachments.
-   *
-   * - `current` renders the embedded content using the latest version.
-   * - `version-at-save` renders the embedded content using the version at the time of save.
-   */
-  embeddedContentRender?: string;
-
-  additionalProperties?: any[];
-}
diff --git a/src/api/parameters/copyPage.ts b/src/api/parameters/copyPage.ts
deleted file mode 100644
index 99781486..00000000
--- a/src/api/parameters/copyPage.ts
+++ /dev/null
@@ -1,9 +0,0 @@
-import type { CopyPageRequest } from '../models';
-
-export interface CopyPage {
-  id: string;
-  destinationPageId: string;
-  expand: string[];
-
-  bodyParameters: CopyPageRequest;
-}
diff --git a/src/api/parameters/copyPageHierarchy.ts b/src/api/parameters/copyPageHierarchy.ts
deleted file mode 100644
index 02047791..00000000
--- a/src/api/parameters/copyPageHierarchy.ts
+++ /dev/null
@@ -1,5 +0,0 @@
-import type { CopyPageHierarchyRequest } from '../models';
-
-export interface CopyPageHierarchy extends CopyPageHierarchyRequest {
-  id: string;
-}
diff --git a/src/api/parameters/createAttachments.ts b/src/api/parameters/createAttachments.ts
deleted file mode 100644
index fd3fe464..00000000
--- a/src/api/parameters/createAttachments.ts
+++ /dev/null
@@ -1,16 +0,0 @@
-import type { OneOrMany } from '~/interfaces';
-
-export interface CreateAttachments {
-  /** The ID of the content to add the attachment to. */
-  id: string;
-  /** The status of the content that the attachment is being added to. */
-  status?: 'current' | 'draft' | string;
-  /** The attachments to be created. */
-  attachments: OneOrMany<{
-    file: Buffer | ReadableStream | string | Blob | File;
-    filename: string;
-    minorEdit: boolean;
-    contentType?: string;
-    comment?: string;
-  }>;
-}
diff --git a/src/api/parameters/createAuditRecord.ts b/src/api/parameters/createAuditRecord.ts
deleted file mode 100644
index 3014d116..00000000
--- a/src/api/parameters/createAuditRecord.ts
+++ /dev/null
@@ -1,3 +0,0 @@
-import type { AuditRecordCreate } from '../models';
-
-export interface CreateAuditRecord extends AuditRecordCreate {}
diff --git a/src/api/parameters/createContent.ts b/src/api/parameters/createContent.ts
deleted file mode 100644
index cc5754ec..00000000
--- a/src/api/parameters/createContent.ts
+++ /dev/null
@@ -1,42 +0,0 @@
-import type { ContentCreate } from '../models';
-import type { OneOrMany } from '~/interfaces';
-
-export interface CreateContent extends ContentCreate {
-  /** Filter the returned content by status. */
-  status?: string;
-  /** A multi-value parameter indicating which properties of the content to expand. */
-  expand?: OneOrMany<
-    | 'childTypes.all'
-    | 'childTypes.attachment'
-    | 'childTypes.comment'
-    | 'childTypes.page'
-    | 'container'
-    | 'metadata.currentuser'
-    | 'metadata.properties'
-    | 'metadata.labels'
-    | 'metadata.frontend'
-    | 'operations'
-    | 'children.page'
-    | 'children.attachment'
-    | 'children.comment'
-    | 'restrictions.read.restrictions.user'
-    | 'restrictions.read.restrictions.group'
-    | 'restrictions.update.restrictions.user'
-    | 'restrictions.update.restrictions.group'
-    | 'history'
-    | 'history.lastUpdated'
-    | 'history.previousVersion'
-    | 'history.contributors'
-    | 'history.nextVersion'
-    | 'ancestors'
-    | 'body'
-    | 'version'
-    | 'descendants.page'
-    | 'descendants.attachment'
-    | 'descendants.comment'
-    | 'space'
-    | 'extensions.inlineProperties'
-    | 'extensions.resolution'
-    | string
-  >;
-}
diff --git a/src/api/parameters/createContentProperty.ts b/src/api/parameters/createContentProperty.ts
deleted file mode 100644
index 855798ca..00000000
--- a/src/api/parameters/createContentProperty.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-import type { ContentPropertyCreate } from '../models';
-
-export interface CreateContentProperty extends ContentPropertyCreate {
-  /** The ID of the content to add the property to. */
-  id: string;
-}
diff --git a/src/api/parameters/createContentPropertyForKey.ts b/src/api/parameters/createContentPropertyForKey.ts
deleted file mode 100644
index f7661e14..00000000
--- a/src/api/parameters/createContentPropertyForKey.ts
+++ /dev/null
@@ -1,8 +0,0 @@
-import type { ContentPropertyCreateNoKey } from '../models';
-
-export interface CreateContentPropertyForKey extends ContentPropertyCreateNoKey {
-  /** The ID of the content to add the property to. */
-  id: string;
-  /** The key of the content property. Required. */
-  key: string;
-}
diff --git a/src/api/parameters/createContentTemplate.ts b/src/api/parameters/createContentTemplate.ts
deleted file mode 100644
index 5af8c3c1..00000000
--- a/src/api/parameters/createContentTemplate.ts
+++ /dev/null
@@ -1,3 +0,0 @@
-import type { ContentTemplateCreate } from '../models';
-
-export interface CreateContentTemplate extends ContentTemplateCreate {}
diff --git a/src/api/parameters/createGroup.ts b/src/api/parameters/createGroup.ts
deleted file mode 100644
index b0c7933e..00000000
--- a/src/api/parameters/createGroup.ts
+++ /dev/null
@@ -1,3 +0,0 @@
-import type { GroupName } from '../models';
-
-export interface CreateGroup extends GroupName {}
diff --git a/src/api/parameters/createOrUpdateAttachments.ts b/src/api/parameters/createOrUpdateAttachments.ts
deleted file mode 100644
index 8f73b80f..00000000
--- a/src/api/parameters/createOrUpdateAttachments.ts
+++ /dev/null
@@ -1,11 +0,0 @@
-import type { CreateAttachments } from './createAttachments';
-
-export interface CreateOrUpdateAttachments {
-  /** The ID of the content to add the attachment to. */
-  id: string;
-  /** The status of the content that the attachment is being added to. This should always be set to 'current'. */
-  status?: 'current' | 'draft' | string;
-
-  /** The attachments to be created or updated. */
-  attachments: CreateAttachments['attachments'];
-}
diff --git a/src/api/parameters/createPrivateSpace.ts b/src/api/parameters/createPrivateSpace.ts
deleted file mode 100644
index 981fbfcc..00000000
--- a/src/api/parameters/createPrivateSpace.ts
+++ /dev/null
@@ -1,3 +0,0 @@
-import type { SpacePrivateCreate } from '../models';
-
-export interface CreatePrivateSpace extends SpacePrivateCreate {}
diff --git a/src/api/parameters/createRelationship.ts b/src/api/parameters/createRelationship.ts
deleted file mode 100644
index ec6b4061..00000000
--- a/src/api/parameters/createRelationship.ts
+++ /dev/null
@@ -1,44 +0,0 @@
-export interface CreateRelationship {
-  /**
-   * The name of the relationship. This method supports the 'favourite' (i.e. 'save for later') relationship. You can
-   * also specify any other value for this parameter to create a custom relationship type.
-   */
-  relationName: string;
-  /** The source entity type of the relationship. This must be 'user', if the `relationName` is 'favourite'. */
-  sourceType: string;
-  /**
-   * - The identifier for the source entity:
-   *
-   *   - If `sourceType` is 'user', then specify either 'current' (logged-in user) or the user key.
-   *   - If `sourceType` is 'content', then specify the content ID.
-   *   - If `sourceType` is 'space', then specify the space key.
-   */
-  sourceKey: string;
-  /**
-   * The target entity type of the relationship. This must be 'space' or 'content', if the `relationName` is
-   * 'favourite'.
-   */
-  targetType: string;
-  /**
-   * - The identifier for the target entity:
-   *
-   *   - If `sourceType` is 'user', then specify either 'current' (logged-in user) or the user key.
-   *   - If `sourceType` is 'content', then specify the content ID.
-   *   - If `sourceType` is 'space', then specify the space key.
-   */
-  targetKey: string;
-  /** The status of the source. This parameter is only used when the `sourceType` is 'content'. */
-  sourceStatus?: string;
-  /** The status of the target. This parameter is only used when the `targetType` is 'content'. */
-  targetStatus?: string;
-  /**
-   * The version of the source. This parameter is only used when the `sourceType` is 'content' and the `sourceStatus` is
-   * 'historical'.
-   */
-  sourceVersion?: number;
-  /**
-   * The version of the target. This parameter is only used when the `targetType` is 'content' and the `targetStatus` is
-   * 'historical'.
-   */
-  targetVersion?: number;
-}
diff --git a/src/api/parameters/createSpace.ts b/src/api/parameters/createSpace.ts
deleted file mode 100644
index 71a63ecc..00000000
--- a/src/api/parameters/createSpace.ts
+++ /dev/null
@@ -1,3 +0,0 @@
-import type { SpaceCreate } from '../models';
-
-export interface CreateSpace extends SpaceCreate {}
diff --git a/src/api/parameters/createSpaceProperty.ts b/src/api/parameters/createSpaceProperty.ts
deleted file mode 100644
index 12d1e355..00000000
--- a/src/api/parameters/createSpaceProperty.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-import type { SpacePropertyCreate } from '../models';
-
-export interface CreateSpaceProperty extends SpacePropertyCreate {
-  /** The key of the space that the property will be created in. */
-  spaceKey: string;
-}
diff --git a/src/api/parameters/createSpacePropertyForKey.ts b/src/api/parameters/createSpacePropertyForKey.ts
deleted file mode 100644
index 90795fa2..00000000
--- a/src/api/parameters/createSpacePropertyForKey.ts
+++ /dev/null
@@ -1,8 +0,0 @@
-import type { SpacePropertyCreateNoKey } from '../models';
-
-export interface CreateSpacePropertyForKey extends SpacePropertyCreateNoKey {
-  /** The key of the space that the property will be created in. */
-  spaceKey: string;
-  /** The key of the property to be created. */
-  key: string;
-}
diff --git a/src/api/parameters/createUserProperty.ts b/src/api/parameters/createUserProperty.ts
deleted file mode 100644
index 6fc772b7..00000000
--- a/src/api/parameters/createUserProperty.ts
+++ /dev/null
@@ -1,11 +0,0 @@
-import type { UserPropertyCreate } from '../models';
-
-export interface CreateUserProperty extends UserPropertyCreate {
-  /**
-   * The account ID of the user. The accountId uniquely identifies the user across all Atlassian products. For example,
-   * 384093:32b4d9w0-f6a5-3535-11a3-9c8c88d10192
-   */
-  userId: string;
-  /** The key of the user property. */
-  key: string;
-}
diff --git a/src/api/parameters/deleteContent.ts b/src/api/parameters/deleteContent.ts
deleted file mode 100644
index 17461390..00000000
--- a/src/api/parameters/deleteContent.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-export interface DeleteContent {
-  /** The ID of the content to be deleted. */
-  id: string;
-  /** Set this to `trashed`, if the content's status is `trashed` and you want to purge it. */
-  status?: string;
-}
diff --git a/src/api/parameters/deleteContentProperty.ts b/src/api/parameters/deleteContentProperty.ts
deleted file mode 100644
index d117a9ce..00000000
--- a/src/api/parameters/deleteContentProperty.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-export interface DeleteContentProperty {
-  /** The ID of the content that the property belongs to. */
-  id: string;
-  /** The key of the property. */
-  key: string;
-}
diff --git a/src/api/parameters/deleteContentVersion.ts b/src/api/parameters/deleteContentVersion.ts
deleted file mode 100644
index 186a8fae..00000000
--- a/src/api/parameters/deleteContentVersion.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-export interface DeleteContentVersion {
-  /** The ID of the content that the version will be deleted from. */
-  id: string;
-  /** The number of the version to be deleted. The version number starts from 1 up to current version. */
-  versionNumber: number;
-}
diff --git a/src/api/parameters/deleteGroupById.ts b/src/api/parameters/deleteGroupById.ts
deleted file mode 100644
index e3a35d21..00000000
--- a/src/api/parameters/deleteGroupById.ts
+++ /dev/null
@@ -1,4 +0,0 @@
-export interface DeleteGroupById {
-  /** Id of the group to delete. */
-  id: string;
-}
diff --git a/src/api/parameters/deleteLabelFromSpace.ts b/src/api/parameters/deleteLabelFromSpace.ts
deleted file mode 100644
index 35c875a1..00000000
--- a/src/api/parameters/deleteLabelFromSpace.ts
+++ /dev/null
@@ -1,8 +0,0 @@
-export interface DeleteLabelFromSpace {
-  /** The key of the space to remove a labels from. */
-  spaceKey: string;
-  /** The name of the label to remove */
-  name: string;
-  /** The prefix of the label to remove. If not provided defaults to global. */
-  prefix?: string;
-}
diff --git a/src/api/parameters/deletePageTree.ts b/src/api/parameters/deletePageTree.ts
deleted file mode 100644
index c2d4b1be..00000000
--- a/src/api/parameters/deletePageTree.ts
+++ /dev/null
@@ -1,4 +0,0 @@
-export interface DeletePageTree {
-  /** The ID of the content which forms root of the page tree, to be deleted. */
-  id: string;
-}
diff --git a/src/api/parameters/deleteRelationship.ts b/src/api/parameters/deleteRelationship.ts
deleted file mode 100644
index 0acec42b..00000000
--- a/src/api/parameters/deleteRelationship.ts
+++ /dev/null
@@ -1,41 +0,0 @@
-export interface DeleteRelationship {
-  /** The name of the relationship. */
-  relationName: string;
-  /** The source entity type of the relationship. This must be 'user', if the `relationName` is 'favourite'. */
-  sourceType: string;
-  /**
-   * - The identifier for the source entity:
-   *
-   *   - If `sourceType` is 'user', then specify either 'current' (logged-in user) or the user key.
-   *   - If `sourceType` is 'content', then specify the content ID.
-   *   - If `sourceType` is 'space', then specify the space key.
-   */
-  sourceKey: string;
-  /**
-   * The target entity type of the relationship. This must be 'space' or 'content', if the `relationName` is
-   * 'favourite'.
-   */
-  targetType: string;
-  /**
-   * - The identifier for the target entity:
-   *
-   *   - If `sourceType` is 'user', then specify either 'current' (logged-in user) or the user key.
-   *   - If `sourceType` is 'content', then specify the content ID.
-   *   - If `sourceType` is 'space', then specify the space key.
-   */
-  targetKey: string;
-  /** The status of the source. This parameter is only used when the `sourceType` is 'content'. */
-  sourceStatus?: string;
-  /** The status of the target. This parameter is only used when the `targetType` is 'content'. */
-  targetStatus?: string;
-  /**
-   * The version of the source. This parameter is only used when the `sourceType` is 'content' and the `sourceStatus` is
-   * 'historical'.
-   */
-  sourceVersion?: number;
-  /**
-   * The version of the target. This parameter is only used when the `targetType` is 'content' and the `targetStatus` is
-   * 'historical'.
-   */
-  targetVersion?: number;
-}
diff --git a/src/api/parameters/deleteRestrictions.ts b/src/api/parameters/deleteRestrictions.ts
deleted file mode 100644
index 7086ea11..00000000
--- a/src/api/parameters/deleteRestrictions.ts
+++ /dev/null
@@ -1,12 +0,0 @@
-export interface DeleteRestrictions {
-  /** The ID of the content to remove restrictions from. */
-  id: string;
-  /**
-   * A multi-value parameter indicating which properties of the content restrictions (returned in response) to expand.
-   *
-   * - `restrictions.user` returns the piece of content that the restrictions are applied to. Expanded by default.
-   * - `restrictions.group` returns the piece of content that the restrictions are applied to. Expanded by default.
-   * - `content` returns the piece of content that the restrictions are applied to.
-   */
-  expand?: string[];
-}
diff --git a/src/api/parameters/deleteSpace.ts b/src/api/parameters/deleteSpace.ts
deleted file mode 100644
index 980425f5..00000000
--- a/src/api/parameters/deleteSpace.ts
+++ /dev/null
@@ -1,4 +0,0 @@
-export interface DeleteSpace {
-  /** The key of the space to delete. */
-  spaceKey: string;
-}
diff --git a/src/api/parameters/deleteSpaceProperty.ts b/src/api/parameters/deleteSpaceProperty.ts
deleted file mode 100644
index c4a8d4c8..00000000
--- a/src/api/parameters/deleteSpaceProperty.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-export interface DeleteSpaceProperty {
-  /** The key of the space that the property is in. */
-  spaceKey: string;
-  /** The key of the property to be deleted. */
-  key: string;
-}
diff --git a/src/api/parameters/deleteUserProperty.ts b/src/api/parameters/deleteUserProperty.ts
deleted file mode 100644
index df7e5c22..00000000
--- a/src/api/parameters/deleteUserProperty.ts
+++ /dev/null
@@ -1,9 +0,0 @@
-export interface DeleteUserProperty {
-  /**
-   * The account ID of the user. The accountId uniquely identifies the user across all Atlassian products. For example,
-   * 384093:32b4d9w0-f6a5-3535-11a3-9c8c88d10192
-   */
-  userId: string;
-  /** The key of the user property. */
-  key: string;
-}
diff --git a/src/api/parameters/downloadAttachment.ts b/src/api/parameters/downloadAttachment.ts
deleted file mode 100644
index 669d1fa1..00000000
--- a/src/api/parameters/downloadAttachment.ts
+++ /dev/null
@@ -1,17 +0,0 @@
-export interface DownloadAttachment {
-  /** The ID of the content that the attachment is attached to. */
-  id: string;
-  /** The ID of the attachment to download. */
-  attachmentId: string;
-  /**
-   * The version of the attachment. If this parameter is absent, the redirect URI will download the latest version of
-   * the attachment.
-   */
-  version?: number;
-  /**
-   * The statuses allowed on the retrieved attachment. If this parameter is absent, it will default to `current`.
-   *
-   * @default current
-   */
-  status?: string | string[];
-}
diff --git a/src/api/parameters/exportAuditRecords.ts b/src/api/parameters/exportAuditRecords.ts
deleted file mode 100644
index 66059c18..00000000
--- a/src/api/parameters/exportAuditRecords.ts
+++ /dev/null
@@ -1,16 +0,0 @@
-export interface ExportAuditRecords {
-  /**
-   * Filters the exported results to the records on or after the `startDate`. The `startDate` must be specified as a
-   * [timestamp](https://www.unixtimestamp.com/).
-   */
-  startDate?: string;
-  /**
-   * Filters the exported results to the records on or before the `endDate`. The `endDate` must be specified as a
-   * [timestamp](https://www.unixtimestamp.com/).
-   */
-  endDate?: string;
-  /** Filters the exported results to records that have string property values matching the `searchString`. */
-  searchString?: string;
-  /** The format of the export file for the audit records. */
-  format?: string;
-}
diff --git a/src/api/parameters/findSourcesForTarget.ts b/src/api/parameters/findSourcesForTarget.ts
deleted file mode 100644
index 04d187f0..00000000
--- a/src/api/parameters/findSourcesForTarget.ts
+++ /dev/null
@@ -1,50 +0,0 @@
-export interface FindSourcesForTarget {
-  /**
-   * The name of the relationship. This method supports relationships created via [Create
-   * relationship](#api-relation-relationName-from-sourceType-sourceKey-to-targetType-targetKey-put). Note, this method
-   * does not support 'favourite' relationships.
-   */
-  relationName: string;
-  /** The source entity type of the relationship. */
-  sourceType: string;
-  /** The target entity type of the relationship. */
-  targetType: string;
-  /**
-   * The identifier for the target entity:
-   *
-   * - If `targetType` is `user`, then specify either `current` (logged-in user), the user key of the user, or the account
-   *   ID of the user. Note that the user key has been deprecated in favor of the account ID for this parameter. See the
-   *   [migration
-   *   guide](https://developer.atlassian.com/cloud/confluence/deprecation-notice-user-privacy-api-migration-guide/) for
-   *   details.
-   * - If `targetType` is 'content', then specify the content ID.
-   * - If `targetType` is 'space', then specify the space key.
-   */
-  targetKey: string;
-  /** The status of the source. This parameter is only used when the `sourceType` is 'content'. */
-  sourceStatus?: string;
-  /** The status of the target. This parameter is only used when the `targetType` is 'content'. */
-  targetStatus?: string;
-  /**
-   * The version of the source. This parameter is only used when the `sourceType` is 'content' and the `sourceStatus` is
-   * 'historical'.
-   */
-  sourceVersion?: number;
-  /**
-   * The version of the target. This parameter is only used when the `targetType` is 'content' and the `targetStatus` is
-   * 'historical'.
-   */
-  targetVersion?: number;
-  /**
-   * A multi-value parameter indicating which properties of the response object to expand.
-   *
-   * - `relationData` returns information about the relationship, such as who created it and when it was created.
-   * - `source` returns the source entity.
-   * - `target` returns the target entity.
-   */
-  expand?: string[];
-  /** The starting index of the returned relationships. */
-  start?: number;
-  /** The maximum number of relationships to return per page. Note, this may be restricted by fixed system limits. */
-  limit?: number;
-}
diff --git a/src/api/parameters/findTargetFromSource.ts b/src/api/parameters/findTargetFromSource.ts
deleted file mode 100644
index daf1b7d0..00000000
--- a/src/api/parameters/findTargetFromSource.ts
+++ /dev/null
@@ -1,50 +0,0 @@
-export interface FindTargetFromSource {
-  /**
-   * The name of the relationship. This method supports relationships created via [Create
-   * relationship](#api-relation-relationName-from-sourceType-sourceKey-to-targetType-targetKey-put). Note, this method
-   * does not support 'favourite' relationships.
-   */
-  relationName: string;
-  /** The source entity type of the relationship. */
-  sourceType: string;
-  /**
-   * The identifier for the source entity:
-   *
-   * - If `sourceType` is `user`, then specify either `current` (logged-in user), the user key of the user, or the account
-   *   ID of the user. Note that the user key has been deprecated in favor of the account ID for this parameter. See the
-   *   [migration
-   *   guide](https://developer.atlassian.com/cloud/confluence/deprecation-notice-user-privacy-api-migration-guide/) for
-   *   details.
-   * - If `sourceType` is 'content', then specify the content ID.
-   * - If `sourceType` is 'space', then specify the space key.
-   */
-  sourceKey: string;
-  /** The target entity type of the relationship. */
-  targetType: string;
-  /** The status of the source. This parameter is only used when the `sourceType` is 'content'. */
-  sourceStatus?: string;
-  /** The status of the target. This parameter is only used when the `targetType` is 'content'. */
-  targetStatus?: string;
-  /**
-   * The version of the source. This parameter is only used when the `sourceType` is 'content' and the `sourceStatus` is
-   * 'historical'.
-   */
-  sourceVersion?: number;
-  /**
-   * The version of the target. This parameter is only used when the `targetType` is 'content' and the `targetStatus` is
-   * 'historical'.
-   */
-  targetVersion?: number;
-  /**
-   * A multi-value parameter indicating which properties of the response object to expand.
-   *
-   * - `relationData` returns information about the relationship, such as who created it and when it was created.
-   * - `source` returns the source entity.
-   * - `target` returns the target entity.
-   */
-  expand?: string[];
-  /** The starting index of the returned relationships. */
-  start?: number;
-  /** The maximum number of relationships to return per page. Note, this may be restricted by fixed system limits. */
-  limit?: number;
-}
diff --git a/src/api/parameters/getAllLabelContent.ts b/src/api/parameters/getAllLabelContent.ts
deleted file mode 100644
index cb2cde8f..00000000
--- a/src/api/parameters/getAllLabelContent.ts
+++ /dev/null
@@ -1,10 +0,0 @@
-export interface GetAllLabelContent {
-  /** Name of the label to query. */
-  name: string;
-  /** The type of contents that are to be returned. */
-  type?: string;
-  /** The starting offset for the results. */
-  start?: number;
-  /** The number of results to be returned. */
-  limit?: number;
-}
diff --git a/src/api/parameters/getAndAsyncConvertMacroBodyByMacroId.ts b/src/api/parameters/getAndAsyncConvertMacroBodyByMacroId.ts
deleted file mode 100644
index 7ef69efd..00000000
--- a/src/api/parameters/getAndAsyncConvertMacroBodyByMacroId.ts
+++ /dev/null
@@ -1,88 +0,0 @@
-export interface GetAndAsyncConvertMacroBodyByMacroId {
-  /** The ID for the content that contains the macro. */
-  id: string;
-  /**
-   * The version of the content that contains the macro. Specifying `0` as the `version` will return the macro body for
-   * the latest content version.
-   */
-  version: number;
-  /**
-   * The ID of the macro. For apps, this is passed to the macro by the Connect/Forge framework. Otherwise, find the
-   * macro ID by querying the desired content and version, then expanding the body in storage format. For example,
-   * '/content/196611/version/7?expand=content.body.storage'.
-   */
-  macroId: string;
-  /**
-   * The content representation to return the macro in. Currently, the following conversions are allowed:
-   *
-   *     -`export_view` - `styled_view` - `view`;
-   */
-  to: string;
-  /**
-   * If this field is false, the cache will erase its current value and begin a conversion. If this field is true, the
-   * cache will not erase its current value, and will set the status of the result in cache to RERUNNING. Once the data
-   * is updated, the status will change to COMPLETED. Large macros that take long to convert, and who want to show
-   * intermediate, but potentially stale data, immediately should set this field to true. Cache values are stored per
-   * macro per user per content and expansions.
-   */
-  allowCache?: boolean;
-  /**
-   * The space key used for resolving embedded content (page includes, files, and links) in the content body. For
-   * example, if the source content contains the link ``
-   * and the `spaceKeyContext=TEST` parameter is provided, then the link will be converted to a link to the "Example
-   * page" page in the "TEST" space.
-   */
-  spaceKeyContext?: string;
-  /**
-   * Mode used for rendering embedded content, like attachments.
-   *
-   *     - `current` renders the embedded content using the latest version.
-   *     - `version-at-save` renders the embedded content using the version at
-   *     the time of save.
-   */
-  embeddedContentRender?: string;
-  /** A multi-value parameter indicating which properties of the content to expand and populate. */
-  expand?:
-    | 'embeddedContent'
-    | 'mediaToken'
-    | 'webresource.superbatch.metatags'
-    | 'webresource.superbatch.tags.all'
-    | 'webresource.superbatch.tags.css'
-    | 'webresource.superbatch.tags.data'
-    | 'webresource.superbatch.tags.js'
-    | 'webresource.superbatch.uris.all'
-    | 'webresource.superbatch.uris.css'
-    | 'webresource.superbatch.uris.data'
-    | 'webresource.superbatch.uris.js'
-    | 'webresource.tags.all'
-    | 'webresource.tags.css'
-    | 'webresource.tags.data'
-    | 'webresource.tags.js'
-    | 'webresource.uris.all'
-    | 'webresource.uris.css'
-    | 'webresource.uris.data'
-    | 'webresource.uris.js'
-    | (
-        | 'embeddedContent'
-        | 'mediaToken'
-        | 'webresource.superbatch.metatags'
-        | 'webresource.superbatch.tags.all'
-        | 'webresource.superbatch.tags.css'
-        | 'webresource.superbatch.tags.data'
-        | 'webresource.superbatch.tags.js'
-        | 'webresource.superbatch.uris.all'
-        | 'webresource.superbatch.uris.css'
-        | 'webresource.superbatch.uris.data'
-        | 'webresource.superbatch.uris.js'
-        | 'webresource.tags.all'
-        | 'webresource.tags.css'
-        | 'webresource.tags.data'
-        | 'webresource.tags.js'
-        | 'webresource.uris.all'
-        | 'webresource.uris.css'
-        | 'webresource.uris.data'
-        | 'webresource.uris.js'
-    )[]
-    | string
-    | string[];
-}
diff --git a/src/api/parameters/getAndConvertMacroBodyByMacroId.ts b/src/api/parameters/getAndConvertMacroBodyByMacroId.ts
deleted file mode 100644
index 5f1e06c4..00000000
--- a/src/api/parameters/getAndConvertMacroBodyByMacroId.ts
+++ /dev/null
@@ -1,104 +0,0 @@
-export interface GetAndConvertMacroBodyByMacroId {
-  /** The ID for the content that contains the macro. */
-  id: string;
-  /**
-   * The version of the content that contains the macro. Specifying `0` as the `version` will return the macro body for
-   * the latest content version.
-   */
-  version: number;
-  /**
-   * The ID of the macro. This is usually passed by the app that the macro is in. Otherwise, find the macro ID by
-   * querying the desired content and version, then expanding the body in storage format. For example,
-   * '/content/196611/version/7?expand=content.body.storage'.
-   */
-  macroId: string;
-  /** The content representation to return the macro in. */
-  to: string;
-  /**
-   * The space key used for resolving embedded content (page includes, files, and links) in the content body. For
-   * example, if the source content contains the link ``
-   * and the `spaceKeyContext=TEST` parameter is provided, then the link will be converted to a link to the "Example
-   * page" page in the "TEST" space.
-   */
-  spaceKeyContext?: string;
-  /**
-   * Mode used for rendering embedded content, like attachments.
-   *
-   *     - `current` renders the embedded content using the latest version.
-   *     - `version-at-save` renders the embedded content using the version at
-   *     the time of save.
-   */
-  embeddedContentRender?: 'current' | 'version-at-save' | string;
-  /** A multi-value parameter indicating which properties of the content to expand. */
-  expand?:
-    | 'childTypes.all'
-    | 'childTypes.attachment'
-    | 'childTypes.comment'
-    | 'childTypes.page'
-    | 'container'
-    | 'metadata.currentuser'
-    | 'metadata.properties'
-    | 'metadata.labels'
-    | 'metadata.frontend'
-    | 'operations'
-    | 'children.page'
-    | 'children.attachment'
-    | 'children.comment'
-    | 'restrictions.read.restrictions.user'
-    | 'restrictions.read.restrictions.group'
-    | 'restrictions.update.restrictions.user'
-    | 'restrictions.update.restrictions.group'
-    | 'history'
-    | 'history.lastUpdated'
-    | 'history.previousVersion'
-    | 'history.contributors'
-    | 'history.nextVersion'
-    | 'ancestors'
-    | 'body'
-    | 'body.storage'
-    | 'body.view'
-    | 'version'
-    | 'descendants.page'
-    | 'descendants.attachment'
-    | 'descendants.comment'
-    | 'space'
-    | 'extensions.inlineProperties'
-    | 'extensions.resolution'
-    | (
-        | 'childTypes.all'
-        | 'childTypes.attachment'
-        | 'childTypes.comment'
-        | 'childTypes.page'
-        | 'container'
-        | 'metadata.currentuser'
-        | 'metadata.properties'
-        | 'metadata.labels'
-        | 'metadata.frontend'
-        | 'operations'
-        | 'children.page'
-        | 'children.attachment'
-        | 'children.comment'
-        | 'restrictions.read.restrictions.user'
-        | 'restrictions.read.restrictions.group'
-        | 'restrictions.update.restrictions.user'
-        | 'restrictions.update.restrictions.group'
-        | 'history'
-        | 'history.lastUpdated'
-        | 'history.previousVersion'
-        | 'history.contributors'
-        | 'history.nextVersion'
-        | 'ancestors'
-        | 'body'
-        | 'body.storage'
-        | 'body.view'
-        | 'version'
-        | 'descendants.page'
-        | 'descendants.attachment'
-        | 'descendants.comment'
-        | 'space'
-        | 'extensions.inlineProperties'
-        | 'extensions.resolution'
-    )[]
-    | string
-    | string[];
-}
diff --git a/src/api/parameters/getAnonymousUser.ts b/src/api/parameters/getAnonymousUser.ts
deleted file mode 100644
index 0bb765f0..00000000
--- a/src/api/parameters/getAnonymousUser.ts
+++ /dev/null
@@ -1,8 +0,0 @@
-export interface GetAnonymousUser {
-  /**
-   * A multi-value parameter indicating which properties of the user to expand.
-   *
-   * - `operations` returns the operations that the user is allowed to do.
-   */
-  expand?: string[];
-}
diff --git a/src/api/parameters/getAttachments.ts b/src/api/parameters/getAttachments.ts
deleted file mode 100644
index 3e161677..00000000
--- a/src/api/parameters/getAttachments.ts
+++ /dev/null
@@ -1,50 +0,0 @@
-import type { OneOrMany } from '~/interfaces';
-
-export interface GetAttachments {
-  /** The ID of the content to be queried for its attachments. */
-  id: string;
-  /** A multi-value parameter indicating which properties of the content to expand. */
-  expand?: OneOrMany<
-    | 'childTypes.all'
-    | 'childTypes.attachment'
-    | 'childTypes.comment'
-    | 'childTypes.page'
-    | 'container'
-    | 'metadata'
-    | 'metadata.currentuser'
-    | 'metadata.properties'
-    | 'metadata.labels'
-    | 'metadata.frontend'
-    | 'operations'
-    | 'children.page'
-    | 'children.attachment'
-    | 'children.comment'
-    | 'restrictions.read.restrictions.user'
-    | 'restrictions.read.restrictions.group'
-    | 'restrictions.update.restrictions.user'
-    | 'restrictions.update.restrictions.group'
-    | 'history'
-    | 'history.lastUpdated'
-    | 'history.previousVersion'
-    | 'history.contributors'
-    | 'history.nextVersion'
-    | 'ancestors'
-    | 'body'
-    | 'version'
-    | 'descendants.page'
-    | 'descendants.attachment'
-    | 'descendants.comment'
-    | 'space'
-    | 'extensions.inlineProperties'
-    | 'extensions.resolution'
-    | string
-  >;
-  /** The starting index of the returned attachments. */
-  start?: number;
-  /** The maximum number of attachments to return per page. Note, this may be restricted by fixed system limits. */
-  limit?: number;
-  /** Filter the results to attachments that match the filename. */
-  filename?: string;
-  /** Filter the results to attachments that match the media type. */
-  mediaType?: string;
-}
diff --git a/src/api/parameters/getAuditRecords.ts b/src/api/parameters/getAuditRecords.ts
deleted file mode 100644
index 8f936a33..00000000
--- a/src/api/parameters/getAuditRecords.ts
+++ /dev/null
@@ -1,18 +0,0 @@
-export interface GetAuditRecords {
-  /**
-   * Filters the results to the records on or after the `startDate`. The `startDate` must be specified as a
-   * [timestamp](https://www.unixtimestamp.com/).
-   */
-  startDate?: string;
-  /**
-   * Filters the results to the records on or before the `endDate`. The `endDate` must be specified as a
-   * [timestamp](https://www.unixtimestamp.com/).
-   */
-  endDate?: string;
-  /** Filters the results to records that have string property values matching the `searchString`. */
-  searchString?: string;
-  /** The starting index of the returned records. */
-  start?: number;
-  /** The maximum number of records to return per page. Note, this may be restricted by fixed system limits. */
-  limit?: number;
-}
diff --git a/src/api/parameters/getAuditRecordsForTimePeriod.ts b/src/api/parameters/getAuditRecordsForTimePeriod.ts
deleted file mode 100644
index 5f9a28f7..00000000
--- a/src/api/parameters/getAuditRecordsForTimePeriod.ts
+++ /dev/null
@@ -1,12 +0,0 @@
-export interface GetAuditRecordsForTimePeriod {
-  /** The number of units for the time period. */
-  number?: number;
-  /** The unit of time that the time period is measured in. */
-  units?: string;
-  /** Filters the results to records that have string property values matching the `searchString`. */
-  searchString?: string;
-  /** The starting index of the returned records. */
-  start?: number;
-  /** The maximum number of records to return per page. Note, this may be restricted by fixed system limits. */
-  limit?: number;
-}
diff --git a/src/api/parameters/getAvailableContentStates.ts b/src/api/parameters/getAvailableContentStates.ts
deleted file mode 100644
index 352464c1..00000000
--- a/src/api/parameters/getAvailableContentStates.ts
+++ /dev/null
@@ -1,4 +0,0 @@
-export interface GetAvailableContentStates {
-  /** Id of content to get available states for */
-  id?: string;
-}
diff --git a/src/api/parameters/getBlueprintTemplates.ts b/src/api/parameters/getBlueprintTemplates.ts
deleted file mode 100644
index 433379b1..00000000
--- a/src/api/parameters/getBlueprintTemplates.ts
+++ /dev/null
@@ -1,17 +0,0 @@
-export interface GetBlueprintTemplates {
-  /**
-   * The key of the space to be queried for templates. If the `spaceKey` is not specified, global blueprint templates
-   * will be returned.
-   */
-  spaceKey?: string;
-  /** The starting index of the returned templates. */
-  start?: number;
-  /** The maximum number of templates to return per page. Note, this may be restricted by fixed system limits. */
-  limit?: number;
-  /**
-   * A multi-value parameter indicating which properties of the template to expand.
-   *
-   * - `body` returns the content of the template in storage format.
-   */
-  expand?: string[];
-}
diff --git a/src/api/parameters/getBulkUserLookup.ts b/src/api/parameters/getBulkUserLookup.ts
deleted file mode 100644
index 30360cd4..00000000
--- a/src/api/parameters/getBulkUserLookup.ts
+++ /dev/null
@@ -1,16 +0,0 @@
-export interface GetBulkUserLookup {
-  /** A list of accountId's of users to be returned. */
-  accountId: string;
-  /**
-   * A multi-value parameter indicating which properties of the user to expand.
-   *
-   * - `operations` returns the operations that the user is allowed to do.
-   * - PersonalSpace returns the user's personal space, if it exists.
-   */
-  expand?: string[];
-  /**
-   * The maximum number of results returned. Currently API returns 200 results max. If more that 200 ids are passed
-   * first 200 will be returned.
-   */
-  limit?: number;
-}
diff --git a/src/api/parameters/getBulkUserMigration.ts b/src/api/parameters/getBulkUserMigration.ts
deleted file mode 100644
index a367ca3b..00000000
--- a/src/api/parameters/getBulkUserMigration.ts
+++ /dev/null
@@ -1,16 +0,0 @@
-export interface GetBulkUserMigration {
-  /**
-   * The key of a user. To specify multiple users, pass multiple key parameters separated by ampersands. For example,
-   * key=mia&key=alana. Required if username isn't provided. Cannot be provided if username is present.
-   */
-  key: string[];
-  /**
-   * The username of a user. To specify multiple users, pass multiple username parameters separated by ampersands. For
-   * example, username=mia&username=alana. Required if key isn't provided. Cannot be provided if key is present.
-   */
-  username?: string[];
-  /** The index of the first item to return in a page of results (page offset). */
-  start?: number;
-  /** The maximum number of results to return per page. Note, this may be restricted by fixed system limits. */
-  limit?: number;
-}
diff --git a/src/api/parameters/getContent.ts b/src/api/parameters/getContent.ts
deleted file mode 100644
index bdeed6ab..00000000
--- a/src/api/parameters/getContent.ts
+++ /dev/null
@@ -1,69 +0,0 @@
-import type { OneOrMany } from '~/interfaces';
-
-export interface GetContent {
-  /** The type of content to return. */
-  type?: string;
-  /** The key of the space to be queried for its content. */
-  spaceKey?: string;
-  /** The title of the page to be returned. Required for page type. */
-  title?: string;
-  /**
-   * Filter the results to a set of content based on their status. If set to `any`, content with any status is returned.
-   * Note, the `historical` status is currently not supported.
-   */
-  status?: string[];
-  /**
-   * The posting date of the blog post to be returned. Required for blogpost type. Format:
-   * yyyy-mm-dd.
-   */
-  postingDay?: string;
-  /** A multi-value parameter indicating which properties of the content to expand. */
-  expand?: OneOrMany<
-    | 'childTypes.all'
-    | 'childTypes.attachment'
-    | 'childTypes.comment'
-    | 'childTypes.page'
-    | 'container'
-    | 'metadata.currentuser'
-    | 'metadata.properties'
-    | 'metadata.labels'
-    | 'metadata.frontend'
-    | 'operations'
-    | 'children.page'
-    | 'children.attachment'
-    | 'children.comment'
-    | 'restrictions.read.restrictions.user'
-    | 'restrictions.read.restrictions.group'
-    | 'restrictions.update.restrictions.user'
-    | 'restrictions.update.restrictions.group'
-    | 'history'
-    | 'history.lastUpdated'
-    | 'history.previousVersion'
-    | 'history.contributors'
-    | 'history.nextVersion'
-    | 'ancestors'
-    | 'body'
-    | 'version'
-    | 'descendants.page'
-    | 'descendants.attachment'
-    | 'descendants.comment'
-    | 'space'
-    | 'extensions.inlineProperties'
-    | 'extensions.resolution'
-    | string
-  >;
-  /**
-   * If set to `viewed`, the request will trigger a 'viewed' event for the content. When this event is triggered, the
-   * page/blogpost will appear on the 'Recently visited' tab of the user's Confluence dashboard.
-   */
-  trigger?: string;
-  /**
-   * Orders the content by a particular field. Specify the field and sort direction for this parameter, as follows:
-   * 'fieldpath asc/desc'. For example, 'history.createdDate desc'.
-   */
-  orderby?: string;
-  /** The starting index of the returned content. */
-  start?: number;
-  /** The maximum number of content objects to return per page. Note, this may be restricted by fixed system limits. */
-  limit?: number;
-}
diff --git a/src/api/parameters/getContentById.ts b/src/api/parameters/getContentById.ts
deleted file mode 100644
index 2462202a..00000000
--- a/src/api/parameters/getContentById.ts
+++ /dev/null
@@ -1,63 +0,0 @@
-import type { OneOrMany } from '~/interfaces';
-
-export interface GetContentById {
-  /**
-   * The ID of the content to be returned. If you don't know the content ID, use [Get content](#api-content-get) and
-   * filter the results.
-   */
-  id: string;
-  /**
-   * Filter the results to a set of content based on their status. If set to `any`, content with any status is returned.
-   * Note, the `historical` status is currently not supported.
-   */
-  status?: string[];
-  /** The version number of the content to be returned. */
-  version?: number;
-  /**
-   * The version of embedded content (e.g. attachments) to render.
-   *
-   * - current renders the latest version of the embedded content.
-   * - version-at-save renders the version of the embedded content at the time of save.
-   */
-  embeddedContentRender?: string;
-  /** A multi-value parameter indicating which properties of the content to expand. */
-  expand?: OneOrMany<
-    | 'childTypes.all'
-    | 'childTypes.attachment'
-    | 'childTypes.comment'
-    | 'childTypes.page'
-    | 'container'
-    | 'metadata.currentuser'
-    | 'metadata.properties'
-    | 'metadata.labels'
-    | 'metadata.frontend'
-    | 'operations'
-    | 'children.page'
-    | 'children.attachment'
-    | 'children.comment'
-    | 'restrictions.read.restrictions.user'
-    | 'restrictions.read.restrictions.group'
-    | 'restrictions.update.restrictions.user'
-    | 'restrictions.update.restrictions.group'
-    | 'history'
-    | 'history.lastUpdated'
-    | 'history.previousVersion'
-    | 'history.contributors'
-    | 'history.nextVersion'
-    | 'ancestors'
-    | 'body'
-    | 'version'
-    | 'descendants.page'
-    | 'descendants.attachment'
-    | 'descendants.comment'
-    | 'space'
-    | 'extensions.inlineProperties'
-    | 'extensions.resolution'
-    | string
-  >;
-  /**
-   * If set to `viewed`, the request will trigger a 'viewed' event for the content. When this event is triggered, the
-   * page/blogpost will appear on the 'Recently visited' tab of the user's Confluence dashboard.
-   */
-  trigger?: string;
-}
diff --git a/src/api/parameters/getContentByTypeForSpace.ts b/src/api/parameters/getContentByTypeForSpace.ts
deleted file mode 100644
index ae49421b..00000000
--- a/src/api/parameters/getContentByTypeForSpace.ts
+++ /dev/null
@@ -1,14 +0,0 @@
-export interface GetContentByTypeForSpace {
-  /** The key of the space to be queried for its content. */
-  spaceKey: string;
-  /** The type of content to return. */
-  type: string;
-  /** Filter the results to content at the root level of the space or all content. */
-  depth?: string;
-  /** A multi-value parameter indicating which properties of the content to expand. */
-  expand?: string[];
-  /** The starting index of the returned content. */
-  start?: number;
-  /** The maximum number of content objects to return per page. Note, this may be restricted by fixed system limits. */
-  limit?: number;
-}
diff --git a/src/api/parameters/getContentChildren.ts b/src/api/parameters/getContentChildren.ts
deleted file mode 100644
index 0e08c893..00000000
--- a/src/api/parameters/getContentChildren.ts
+++ /dev/null
@@ -1,21 +0,0 @@
-import type { OneOrMany } from '../../interfaces';
-
-export interface GetContentChildren {
-  /** The ID of the content to be queried for its children. */
-  id: string;
-  /**
-   * A multi-value parameter indicating which properties of the children to expand, where:
-   *
-   * - `attachment` returns all attachments for the content.
-   * - `comments` returns all comments for the content.
-   * - `page` returns all child pages of the content.
-   * - Custom content types that are provided by apps are also supported.
-   */
-  expand?: OneOrMany<'attachment' | 'comments' | 'page' | string>;
-  /** The version of the parent content to retrieve children for. Currently, this only works for the latest version. */
-  parentVersion?: number;
-  /** The starting index of the returned content children. */
-  start?: number;
-  /** The maximum number of content children to return per page. */
-  limit?: number;
-}
diff --git a/src/api/parameters/getContentChildrenByType.ts b/src/api/parameters/getContentChildrenByType.ts
deleted file mode 100644
index 01f08466..00000000
--- a/src/api/parameters/getContentChildrenByType.ts
+++ /dev/null
@@ -1,14 +0,0 @@
-export interface GetContentChildrenByType {
-  /** The ID of the content to be queried for its children. */
-  id: string;
-  /** The type of children to return. */
-  type: string;
-  /** A multi-value parameter indicating which properties of the content to expand. */
-  expand?: string[];
-  /** The version of the parent content to retrieve children for. Currently, this only works for the latest version. */
-  parentVersion?: number;
-  /** The starting index of the returned content. */
-  start?: number;
-  /** The maximum number of content to return per page. Note, this may be restricted by fixed system limits. */
-  limit?: number;
-}
diff --git a/src/api/parameters/getContentComments.ts b/src/api/parameters/getContentComments.ts
deleted file mode 100644
index 020992cf..00000000
--- a/src/api/parameters/getContentComments.ts
+++ /dev/null
@@ -1,19 +0,0 @@
-export interface GetContentComments {
-  /** The ID of the content to be queried for its comments. */
-  id: string;
-  /** A multi-value parameter indicating which properties of the content to expand. */
-  expand?: string[];
-  /** The version of the parent content to retrieve children for. Currently, this only works for the latest version. */
-  parentVersion?: number;
-  /** The starting index of the returned comments. */
-  start?: number;
-  /** The maximum number of comments to return per page. Note, this may be restricted by fixed system limits. */
-  limit?: number;
-  /**
-   * The location of the comments in the page. Multiple locations can be specified. If no location is specified,
-   * comments from all locations are returned.
-   */
-  location?: string[];
-  /** Currently, this parameter is not used. Comments are returned at the root level only. */
-  depth?: string;
-}
diff --git a/src/api/parameters/getContentDescendants.ts b/src/api/parameters/getContentDescendants.ts
deleted file mode 100644
index 6f708ab0..00000000
--- a/src/api/parameters/getContentDescendants.ts
+++ /dev/null
@@ -1,12 +0,0 @@
-export interface GetContentDescendants {
-  /** The ID of the content to be queried for its descendants. */
-  id: string;
-  /**
-   * A multi-value parameter indicating which properties of the children to expand, where:
-   *
-   * - `attachment` returns all attachments for the content.
-   * - `comments` returns all comments for the content.
-   * - `page` returns all child pages of the content.
-   */
-  expand?: string[];
-}
diff --git a/src/api/parameters/getContentForSpace.ts b/src/api/parameters/getContentForSpace.ts
deleted file mode 100644
index 26cae921..00000000
--- a/src/api/parameters/getContentForSpace.ts
+++ /dev/null
@@ -1,12 +0,0 @@
-export interface GetContentForSpace {
-  /** The key of the space to be queried for its content. */
-  spaceKey: string;
-  /** Filter the results to content at the root level of the space or all content. */
-  depth?: string;
-  /** A multi-value parameter indicating which properties of the content to expand. */
-  expand?: string[];
-  /** The starting index of the returned content. */
-  start?: number;
-  /** The maximum number of content objects to return per page. Note, this may be restricted by fixed system limits. */
-  limit?: number;
-}
diff --git a/src/api/parameters/getContentProperties.ts b/src/api/parameters/getContentProperties.ts
deleted file mode 100644
index 977a4d33..00000000
--- a/src/api/parameters/getContentProperties.ts
+++ /dev/null
@@ -1,19 +0,0 @@
-export interface GetContentProperties {
-  /** The ID of the content to be queried for its properties. */
-  id: string;
-  /** The key of the content property. */
-  key?: string[];
-  /**
-   * A multi-value parameter indicating which properties of the content to expand. By default, the `version` object is
-   * expanded.
-   *
-   * - `content` returns the content that the property is stored against.
-   * - `version` returns information about the version of the property, such as the version number, when it was created,
-   *   etc.
-   */
-  expand?: string[];
-  /** The starting index of the returned properties. */
-  start?: number;
-  /** The maximum number of properties to return per page. Note, this may be restricted by fixed system limits. */
-  limit?: number;
-}
diff --git a/src/api/parameters/getContentProperty.ts b/src/api/parameters/getContentProperty.ts
deleted file mode 100644
index fae016d2..00000000
--- a/src/api/parameters/getContentProperty.ts
+++ /dev/null
@@ -1,27 +0,0 @@
-export interface GetContentProperty {
-  /** The ID of the content to be queried for the property. */
-  id: string;
-  /** The key of the content property. */
-  key: string;
-  /**
-   * A multi-value parameter indicating which properties of the content to expand. By default, the `version` object is
-   * expanded.
-   *
-   * - `content` returns the content that the property is stored against.
-   * - `version` returns information about the version of the property, such as the version number, when it was created,
-   *   etc.
-   */
-  expand?: string[];
-  /**
-   * Filter the results to a set of content based on their status. If set to `any`, content with any status is returned.
-   * By default it will fetch current and archived statuses `?status=current&status=archived`. All supported statuses
-   *
-   * - Any
-   * - Archived
-   * - Current
-   * - Deleted
-   * - Draft
-   * - Trashed
-   */
-  status?: string[];
-}
diff --git a/src/api/parameters/getContentRestrictionStatusForGroup.ts b/src/api/parameters/getContentRestrictionStatusForGroup.ts
deleted file mode 100644
index 9d9c8d60..00000000
--- a/src/api/parameters/getContentRestrictionStatusForGroup.ts
+++ /dev/null
@@ -1,8 +0,0 @@
-export interface GetContentRestrictionStatusForGroup {
-  /** The ID of the content that the restriction applies to. */
-  id: string;
-  /** The operation that the restriction applies to. */
-  operationKey: string;
-  /** The name of the group to be queried for whether the content restriction applies to it. */
-  groupName: string;
-}
diff --git a/src/api/parameters/getContentRestrictionStatusForUser.ts b/src/api/parameters/getContentRestrictionStatusForUser.ts
deleted file mode 100644
index 7043ad37..00000000
--- a/src/api/parameters/getContentRestrictionStatusForUser.ts
+++ /dev/null
@@ -1,21 +0,0 @@
-export interface GetContentRestrictionStatusForUser {
-  /** The ID of the content that the restriction applies to. */
-  id: string;
-  /** The operation that is restricted. */
-  operationKey: string;
-  /**
-   * This parameter is no longer available and will be removed from the documentation soon. Use `accountId` instead. See
-   * the [deprecation notice](/cloud/confluence/deprecation-notice-user-privacy-api-migration-guide/) for details.
-   */
-  key?: string;
-  /**
-   * This parameter is no longer available and will be removed from the documentation soon. Use `accountId` instead. See
-   * the [deprecation notice](/cloud/confluence/deprecation-notice-user-privacy-api-migration-guide/) for details.
-   */
-  userName?: string;
-  /**
-   * The account ID of the user to be queried for whether the content restriction applies to it. The accountId uniquely
-   * identifies the user across all Atlassian products. For example, `384093:32b4d9w0-f6a5-3535-11a3-9c8c88d10192`.
-   */
-  accountId: string;
-}
diff --git a/src/api/parameters/getContentState.ts b/src/api/parameters/getContentState.ts
deleted file mode 100644
index f45338b7..00000000
--- a/src/api/parameters/getContentState.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-export interface GetContentState {
-  /** The id of the content whose content state is of interest. */
-  id?: string;
-  /** Set status to one of [current,draft,archived]. */
-  status?: 'current' | 'draft' | 'archived' | string;
-}
diff --git a/src/api/parameters/getContentStateSettings.ts b/src/api/parameters/getContentStateSettings.ts
deleted file mode 100644
index 37fb0723..00000000
--- a/src/api/parameters/getContentStateSettings.ts
+++ /dev/null
@@ -1,4 +0,0 @@
-export interface GetContentStateSettings {
-  /** SpaceKey */
-  spaceKey: string;
-}
diff --git a/src/api/parameters/getContentTemplate.ts b/src/api/parameters/getContentTemplate.ts
deleted file mode 100644
index 787569e9..00000000
--- a/src/api/parameters/getContentTemplate.ts
+++ /dev/null
@@ -1,4 +0,0 @@
-export interface GetContentTemplate {
-  /** The ID of the content template to be returned. */
-  contentTemplateId: string;
-}
diff --git a/src/api/parameters/getContentTemplates.ts b/src/api/parameters/getContentTemplates.ts
deleted file mode 100644
index 74cbb06e..00000000
--- a/src/api/parameters/getContentTemplates.ts
+++ /dev/null
@@ -1,17 +0,0 @@
-export interface GetContentTemplates {
-  /**
-   * The key of the space to be queried for templates. If the `spaceKey` is not specified, global templates will be
-   * returned.
-   */
-  spaceKey?: string;
-  /** The starting index of the returned templates. */
-  start?: number;
-  /** The maximum number of templates to return per page. Note, this may be restricted by fixed system limits. */
-  limit?: number;
-  /**
-   * A multi-value parameter indicating which properties of the template to expand.
-   *
-   * - `body` returns the content of the template in storage format.
-   */
-  expand?: string[];
-}
diff --git a/src/api/parameters/getContentVersion.ts b/src/api/parameters/getContentVersion.ts
deleted file mode 100644
index 1fe1e753..00000000
--- a/src/api/parameters/getContentVersion.ts
+++ /dev/null
@@ -1,14 +0,0 @@
-export interface GetContentVersion {
-  /** The ID of the content to be queried for its version. */
-  id: string;
-  /** The number of the version to be retrieved. */
-  versionNumber: number;
-  /**
-   * A multi-value parameter indicating which properties of the content to expand. By default, the `content` object is
-   * expanded.
-   *
-   * - `collaborators` returns the users that collaborated on the version.
-   * - `content` returns the content for the version.
-   */
-  expand?: string[];
-}
diff --git a/src/api/parameters/getContentVersions.ts b/src/api/parameters/getContentVersions.ts
deleted file mode 100644
index f1ee4a41..00000000
--- a/src/api/parameters/getContentVersions.ts
+++ /dev/null
@@ -1,16 +0,0 @@
-export interface GetContentVersions {
-  /** The ID of the content to be queried for its versions. */
-  id: string;
-  /** The starting index of the returned versions. */
-  start?: number;
-  /** The maximum number of versions to return per page. Note, this may be restricted by fixed system limits. */
-  limit?: number;
-  /**
-   * A multi-value parameter indicating which properties of the content to expand. By default, the `content` object is
-   * expanded.
-   *
-   * - `collaborators` returns the users that collaborated on the version.
-   * - `content` returns the content for the version.
-   */
-  expand?: string[];
-}
diff --git a/src/api/parameters/getContentWatchStatus.ts b/src/api/parameters/getContentWatchStatus.ts
deleted file mode 100644
index f32174cb..00000000
--- a/src/api/parameters/getContentWatchStatus.ts
+++ /dev/null
@@ -1,19 +0,0 @@
-export interface GetContentWatchStatus {
-  /** The ID of the content to be queried for whether the specified user is watching it. */
-  contentId: string;
-  /**
-   * This parameter is no longer available and will be removed from the documentation soon. Use `accountId` instead. See
-   * the [deprecation notice](/cloud/confluence/deprecation-notice-user-privacy-api-migration-guide/) for details.
-   */
-  key?: string;
-  /**
-   * This parameter is no longer available and will be removed from the documentation soon. Use `accountId` instead. See
-   * the [deprecation notice](/cloud/confluence/deprecation-notice-user-privacy-api-migration-guide/) for details.
-   */
-  username?: string;
-  /**
-   * The `accountId` of the user to be queried for whether they are watching the content. The accountId uniquely
-   * identifies the user across all Atlassian products. For example, `384093:32b4d9w0-f6a5-3535-11a3-9c8c88d10192`.
-   */
-  accountId: string;
-}
diff --git a/src/api/parameters/getContentsWithState.ts b/src/api/parameters/getContentsWithState.ts
deleted file mode 100644
index 0eb99e8c..00000000
--- a/src/api/parameters/getContentsWithState.ts
+++ /dev/null
@@ -1,17 +0,0 @@
-export interface GetContentsWithState {
-  /** The key of the space to be queried for its content state settings. */
-  spaceKey: string;
-  /** The id of the content state to filter content by */
-  stateId: number;
-  /**
-   * A multi-value parameter indicating which properties of the content to expand. Options include: space, version,
-   * history, children, etc.
-   *
-   *     Ex: (space, version);
-   */
-  expand?: string[];
-  /** Maximum number of results to return */
-  limit?: number;
-  /** Number of result to start returning. (0 indexed) */
-  start?: number;
-}
diff --git a/src/api/parameters/getCurrentUser.ts b/src/api/parameters/getCurrentUser.ts
deleted file mode 100644
index 2f1da839..00000000
--- a/src/api/parameters/getCurrentUser.ts
+++ /dev/null
@@ -1,10 +0,0 @@
-export interface GetCurrentUser {
-  /**
-   * A multi-value parameter indicating which properties of the user to expand.
-   *
-   * - `operations` returns the operations that the user is allowed to do.
-   * - PersonalSpace returns the user's personal space, if it exists.
-   * - `isExternalCollaborator` returns whether the user is an external collaborator user
-   */
-  expand?: string[];
-}
diff --git a/src/api/parameters/getDescendantsOfType.ts b/src/api/parameters/getDescendantsOfType.ts
deleted file mode 100644
index 3368c78f..00000000
--- a/src/api/parameters/getDescendantsOfType.ts
+++ /dev/null
@@ -1,52 +0,0 @@
-import type { OneOrMany } from '~/interfaces';
-
-export interface GetDescendantsOfType {
-  /** The ID of the content to be queried for its descendants. */
-  id: string;
-  /** The type of descendants to return. */
-  type: string | 'page' | 'comment' | 'attachment';
-  /**
-   * Filter the results to descendants upto a desired level of the content. Note, the maximum value supported is 100.
-   * root level of the content means immediate (level 1) descendants of the type requested. all represents returning all
-   * descendants of the type requested.
-   */
-  depth?: string;
-  /** The starting index of the returned content. */
-  start?: number;
-  /** The maximum number of content to return per page. Note, this may be restricted by fixed system limits. */
-  limit?: number;
-  expand?: OneOrMany<
-    | 'childTypes.all'
-    | 'childTypes.attachment'
-    | 'childTypes.comment'
-    | 'childTypes.page'
-    | 'container'
-    | 'metadata.currentuser'
-    | 'metadata.properties'
-    | 'metadata.labels'
-    | 'metadata.frontend'
-    | 'operations'
-    | 'children.page'
-    | 'children.attachment'
-    | 'children.comment'
-    | 'restrictions.read.restrictions.user'
-    | 'restrictions.read.restrictions.group'
-    | 'restrictions.update.restrictions.user'
-    | 'restrictions.update.restrictions.group'
-    | 'history'
-    | 'history.lastUpdated'
-    | 'history.previousVersion'
-    | 'history.contributors'
-    | 'history.nextVersion'
-    | 'ancestors'
-    | 'body'
-    | 'version'
-    | 'descendants.page'
-    | 'descendants.attachment'
-    | 'descendants.comment'
-    | 'space'
-    | 'extensions.inlineProperties'
-    | 'extensions.resolution'
-    | string
-  >;
-}
diff --git a/src/api/parameters/getGroupByGroupId.ts b/src/api/parameters/getGroupByGroupId.ts
deleted file mode 100644
index 6cb738a6..00000000
--- a/src/api/parameters/getGroupByGroupId.ts
+++ /dev/null
@@ -1,4 +0,0 @@
-export interface GetGroupByGroupId {
-  /** The id of the group. */
-  id: string;
-}
diff --git a/src/api/parameters/getGroupByName.ts b/src/api/parameters/getGroupByName.ts
deleted file mode 100644
index 99a9aaad..00000000
--- a/src/api/parameters/getGroupByName.ts
+++ /dev/null
@@ -1,4 +0,0 @@
-export interface GetGroupByName {
-  /** The name of the group. This is the same as the group name shown in the Confluence administration console. */
-  groupName: string;
-}
diff --git a/src/api/parameters/getGroupByQueryParam.ts b/src/api/parameters/getGroupByQueryParam.ts
deleted file mode 100644
index 069114bd..00000000
--- a/src/api/parameters/getGroupByQueryParam.ts
+++ /dev/null
@@ -1,4 +0,0 @@
-export interface GetGroupByQueryParam {
-  /** The name of the group. This is the same as the group name shown in the Confluence administration console. */
-  name: string;
-}
diff --git a/src/api/parameters/getGroupMembers.ts b/src/api/parameters/getGroupMembers.ts
deleted file mode 100644
index 3abf348f..00000000
--- a/src/api/parameters/getGroupMembers.ts
+++ /dev/null
@@ -1,8 +0,0 @@
-export interface GetGroupMembers {
-  /** The name of the group to be queried for its members. */
-  groupName: string;
-  /** The starting index of the returned users. */
-  start?: number;
-  /** The maximum number of users to return per page. Note, this may be restricted by fixed system limits. */
-  limit?: number;
-}
diff --git a/src/api/parameters/getGroupMembersByGroupId.ts b/src/api/parameters/getGroupMembersByGroupId.ts
deleted file mode 100644
index 8ce74ee5..00000000
--- a/src/api/parameters/getGroupMembersByGroupId.ts
+++ /dev/null
@@ -1,20 +0,0 @@
-export interface GetGroupMembersByGroupId {
-  /** The id of the group to be queried for its members. */
-  groupId: string;
-  /** The starting index of the returned users. */
-  start?: number;
-  /** The maximum number of users to return per page. Note, this may be restricted by fixed system limits. */
-  limit?: number;
-  /**
-   * Whether to include total size parameter in the results. Note, fetching total size property is an expensive
-   * operation; use it if your use case needs this value.
-   */
-  shouldReturnTotalSize?: boolean;
-  /**
-   * A multi-value parameter indicating which properties of the user to expand.
-   *
-   * - `operations` returns the operations that the user is allowed to do.
-   * - `personalSpace` returns the user's personal space, if it exists.
-   */
-  expand?: 'operations' | 'personalSpace' | string | ('operations' | 'personalSpace' | string)[];
-}
diff --git a/src/api/parameters/getGroupMembershipsForUser.ts b/src/api/parameters/getGroupMembershipsForUser.ts
deleted file mode 100644
index a38603a8..00000000
--- a/src/api/parameters/getGroupMembershipsForUser.ts
+++ /dev/null
@@ -1,25 +0,0 @@
-export interface GetGroupMembershipsForUser {
-  /**
-   * This parameter is no longer available and will be removed from the documentation soon. Use `accountId` instead. See
-   * the [deprecation notice](/cloud/confluence/deprecation-notice-user-privacy-api-migration-guide/) for details.
-   *
-   * @deprecated Will be removed in next major version.
-   */
-  key?: string;
-  /**
-   * This parameter is no longer available and will be removed from the documentation soon. Use `accountId` instead. See
-   * the [deprecation notice](/cloud/confluence/deprecation-notice-user-privacy-api-migration-guide/) for details.
-   *
-   * @deprecated Will be removed in next major version.
-   */
-  username?: string;
-  /**
-   * The account ID of the user, which uniquely identifies the user across all Atlassian products. For example,
-   * `384093:32b4d9w0-f6a5-3535-11a3-9c8c88d10192`.
-   */
-  accountId: string;
-  /** The starting index of the returned groups. */
-  start?: number;
-  /** The maximum number of groups to return per page. Note, this may be restricted by fixed system limits. */
-  limit?: number;
-}
diff --git a/src/api/parameters/getGroups.ts b/src/api/parameters/getGroups.ts
deleted file mode 100644
index 9c4d8830..00000000
--- a/src/api/parameters/getGroups.ts
+++ /dev/null
@@ -1,8 +0,0 @@
-export interface GetGroups {
-  /** The starting index of the returned groups. */
-  start?: number;
-  /** The maximum number of groups to return per page. Note, this may be restricted by fixed system limits. */
-  limit?: number;
-  /** The group permission level for which to filter results. */
-  accessType?: string;
-}
diff --git a/src/api/parameters/getHistoryForContent.ts b/src/api/parameters/getHistoryForContent.ts
deleted file mode 100644
index c774f720..00000000
--- a/src/api/parameters/getHistoryForContent.ts
+++ /dev/null
@@ -1,16 +0,0 @@
-export interface GetHistoryForContent {
-  /** The ID of the content to be queried for its history. */
-  id: string;
-  /**
-   * A multi-value parameter indicating which properties of the content history to expand. Maximum sub-expansions
-   * allowed is `8`.
-   *
-   * - `lastUpdated` returns information about the most recent update of the content, including who updated it and when it
-   *   was updated.
-   * - `previousVersion` returns information about the update prior to the current content update. For this method, it
-   *   contains the same information as `lastUpdated`.
-   * - `contributors` returns all of the users who have contributed to the content.
-   * - `nextVersion` This parameter is not used for this method.
-   */
-  expand?: string[];
-}
diff --git a/src/api/parameters/getIndividualGroupRestrictionStatusByGroupId.ts b/src/api/parameters/getIndividualGroupRestrictionStatusByGroupId.ts
deleted file mode 100644
index 355e0cea..00000000
--- a/src/api/parameters/getIndividualGroupRestrictionStatusByGroupId.ts
+++ /dev/null
@@ -1,8 +0,0 @@
-export interface GetIndividualGroupRestrictionStatusByGroupId {
-  /** The ID of the content that the restriction applies to. */
-  id: string;
-  /** The operation that the restriction applies to. */
-  operationKey: string;
-  /** The id of the group to be queried for whether the content restriction applies to it. */
-  groupId: string;
-}
diff --git a/src/api/parameters/getLabelsForContent.ts b/src/api/parameters/getLabelsForContent.ts
deleted file mode 100644
index 2a9a6aa6..00000000
--- a/src/api/parameters/getLabelsForContent.ts
+++ /dev/null
@@ -1,19 +0,0 @@
-export interface GetLabelsForContent {
-  /** The ID of the content to be queried for its labels. */
-  id: string;
-  /**
-   * Filters the results to labels with the specified prefix. If this parameter is not specified, then labels with any
-   * prefix will be returned.
-   *
-   * - `global` prefix is used by default when a user adds a label via the UI.
-   * - `my` prefix can be explicitly added by a user when adding a label via the UI, e.g. 'my:example-label'. Also, when a
-   *   page is selected as a favourite, the 'my:favourite' label is automatically added.
-   * - `team` can used when adding labels via [Add labels to content](#api-content-id-label-post) but is not used in the
-   *   UI.
-   */
-  prefix?: string;
-  /** The starting index of the returned labels. */
-  start?: number;
-  /** The maximum number of labels to return per page. Note, this may be restricted by fixed system limits. */
-  limit?: number;
-}
diff --git a/src/api/parameters/getLabelsForSpace.ts b/src/api/parameters/getLabelsForSpace.ts
deleted file mode 100644
index 6dc68467..00000000
--- a/src/api/parameters/getLabelsForSpace.ts
+++ /dev/null
@@ -1,18 +0,0 @@
-export interface GetLabelsForSpace {
-  /** The key of the space to get labels for. */
-  spaceKey: string;
-  /**
-   * Filters the results to labels with the specified prefix. If this parameter is not specified, then labels with any
-   * prefix will be returned.
-   *
-   *     - `global` prefix is used by labels that are on content within the provided space.
-   *     - `my` prefix can be explicitly added by a user when adding a label
-   *     via the UI, e.g. 'my:example-label'.
-   *     - `team` prefix is used for labels applied to the space.
-   */
-  prefix?: string;
-  /** The starting index of the returned labels. */
-  start?: number;
-  /** The maximum number of labels to return per page. Note, this may be restricted by fixed system limits. */
-  limit?: number;
-}
diff --git a/src/api/parameters/getLookAndFeelSettings.ts b/src/api/parameters/getLookAndFeelSettings.ts
deleted file mode 100644
index acb48664..00000000
--- a/src/api/parameters/getLookAndFeelSettings.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-export interface GetLookAndFeelSettings {
-  /**
-   * The key of the space for which the look and feel settings will be returned. If this is not set, only the global
-   * look and feel settings are returned.
-   */
-  spaceKey?: string;
-}
diff --git a/src/api/parameters/getMacroBodyByMacroId.ts b/src/api/parameters/getMacroBodyByMacroId.ts
deleted file mode 100644
index 70f77e66..00000000
--- a/src/api/parameters/getMacroBodyByMacroId.ts
+++ /dev/null
@@ -1,12 +0,0 @@
-export interface GetMacroBodyByMacroId {
-  /** The ID for the content that contains the macro. */
-  id: string;
-  /** The version of the content that contains the macro. */
-  version: number;
-  /**
-   * The ID of the macro. This is usually passed by the app that the macro is in. Otherwise, find the macro ID by
-   * querying the desired content and version, then expanding the body in storage format. For example,
-   * '/content/196611/version/7?expand=content.body.storage'.
-   */
-  macroId: string;
-}
diff --git a/src/api/parameters/getMembersByQueryParam.ts b/src/api/parameters/getMembersByQueryParam.ts
deleted file mode 100644
index e737f0d6..00000000
--- a/src/api/parameters/getMembersByQueryParam.ts
+++ /dev/null
@@ -1,16 +0,0 @@
-export interface GetMembersByQueryParam {
-  /** The name of the group to be queried for its members. */
-  name: string;
-  /** The starting index of the returned users. */
-  start?: number;
-  /**
-   * The maximum number of users to return per page. Note, this is restricted by fixed system limit of 200 which is to
-   * say if the limit parameter exceeds 200, this API will return a maximum of 200 users per page.
-   */
-  limit?: number;
-  /**
-   * Whether to include total size parameter in the results. Note, fetching total size property is an expensive
-   * operation; use it if your use case needs this value.
-   */
-  shouldReturnTotalSize?: boolean;
-}
diff --git a/src/api/parameters/getPrivacyUnsafeUserEmail.ts b/src/api/parameters/getPrivacyUnsafeUserEmail.ts
deleted file mode 100644
index b32b28d4..00000000
--- a/src/api/parameters/getPrivacyUnsafeUserEmail.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-export interface GetPrivacyUnsafeUserEmail {
-  /**
-   * The account ID of the user, which uniquely identifies the user across all Atlassian products. For example,
-   * `384093:32b4d9w0-f6a5-3535-11a3-9c8c88d10192`. Required.
-   */
-  accountId: string;
-}
diff --git a/src/api/parameters/getPrivacyUnsafeUserEmailBulk.ts b/src/api/parameters/getPrivacyUnsafeUserEmailBulk.ts
deleted file mode 100644
index fd31f38d..00000000
--- a/src/api/parameters/getPrivacyUnsafeUserEmailBulk.ts
+++ /dev/null
@@ -1,4 +0,0 @@
-export interface GetPrivacyUnsafeUserEmailBulk {
-  /** The account IDs of the users. */
-  accountId: string[];
-}
diff --git a/src/api/parameters/getRelationship.ts b/src/api/parameters/getRelationship.ts
deleted file mode 100644
index a246d8aa..00000000
--- a/src/api/parameters/getRelationship.ts
+++ /dev/null
@@ -1,61 +0,0 @@
-export interface GetRelationship {
-  /**
-   * The name of the relationship. This method supports the 'favourite' (i.e. 'save for later') relationship as well as
-   * any other relationship types created via [Create
-   * relationship](#api-relation-relationName-from-sourceType-sourceKey-to-targetType-targetKey-put).
-   */
-  relationName: string;
-  /** The source entity type of the relationship. This must be 'user', if the `relationName` is 'favourite'. */
-  sourceType: string;
-  /**
-   * - The identifier for the source entity:
-   *
-   *   - If `sourceType` is `user`, then specify either `current` (logged-in user), the user key of the user, or the account
-   *       ID of the user. Note that the user key has been deprecated in favor of the account ID for this parameter. See
-   *       the [migration
-   *       guide](https://developer.atlassian.com/cloud/confluence/deprecation-notice-user-privacy-api-migration-guide/)
-   *       for details.
-   *   - If `sourceType` is 'content', then specify the content ID.
-   *   - If `sourceType` is 'space', then specify the space key.
-   */
-  sourceKey: string;
-  /**
-   * The target entity type of the relationship. This must be 'space' or 'content', if the `relationName` is
-   * 'favourite'.
-   */
-  targetType: string;
-  /**
-   * The identifier for the target entity:
-   *
-   * - If `targetType` is `user`, then specify either `current` (logged-in user), the user key of the user, or the account
-   *   ID of the user. Note that the user key has been deprecated in favor of the account ID for this parameter. See the
-   *   [migration
-   *   guide](https://developer.atlassian.com/cloud/confluence/deprecation-notice-user-privacy-api-migration-guide/) for
-   *   details.
-   * - If `targetType` is 'content', then specify the content ID.
-   * - If `targetType` is 'space', then specify the space key.
-   */
-  targetKey: string;
-  /** The status of the source. This parameter is only used when the `sourceType` is 'content'. */
-  sourceStatus?: string;
-  /** The status of the target. This parameter is only used when the `targetType` is 'content'. */
-  targetStatus?: string;
-  /**
-   * The version of the source. This parameter is only used when the `sourceType` is 'content' and the `sourceStatus` is
-   * 'historical'.
-   */
-  sourceVersion?: number;
-  /**
-   * The version of the target. This parameter is only used when the `targetType` is 'content' and the `targetStatus` is
-   * 'historical'.
-   */
-  targetVersion?: number;
-  /**
-   * A multi-value parameter indicating which properties of the response object to expand.
-   *
-   * - `relationData` returns information about the relationship, such as who created it and when it was created.
-   * - `source` returns the source entity.
-   * - `target` returns the target entity.
-   */
-  expand?: string[];
-}
diff --git a/src/api/parameters/getRestrictions.ts b/src/api/parameters/getRestrictions.ts
deleted file mode 100644
index 9202d693..00000000
--- a/src/api/parameters/getRestrictions.ts
+++ /dev/null
@@ -1,20 +0,0 @@
-export interface GetRestrictions {
-  /** The ID of the content to be queried for its restrictions. */
-  id: string;
-  /**
-   * A multi-value parameter indicating which properties of the content restrictions to expand. By default, the
-   * following objects are expanded: `restrictions.user`, `restrictions.group`.
-   *
-   * - `restrictions.user` returns the piece of content that the restrictions are applied to.
-   * - `restrictions.group` returns the piece of content that the restrictions are applied to.
-   * - `content` returns the piece of content that the restrictions are applied to.
-   */
-  expand?: string[];
-  /** The starting index of the users and groups in the returned restrictions. */
-  start?: number;
-  /**
-   * The maximum number of users and the maximum number of groups, in the returned restrictions, to return per page.
-   * Note, this may be restricted by fixed system limits.
-   */
-  limit?: number;
-}
diff --git a/src/api/parameters/getRestrictionsByOperation.ts b/src/api/parameters/getRestrictionsByOperation.ts
deleted file mode 100644
index 5b892d05..00000000
--- a/src/api/parameters/getRestrictionsByOperation.ts
+++ /dev/null
@@ -1,12 +0,0 @@
-export interface GetRestrictionsByOperation {
-  /** The ID of the content to be queried for its restrictions. */
-  id: string;
-  /**
-   * A multi-value parameter indicating which properties of the content restrictions to expand.
-   *
-   * - `restrictions.user` returns the piece of content that the restrictions are applied to. Expanded by default.
-   * - `restrictions.group` returns the piece of content that the restrictions are applied to. Expanded by default.
-   * - `content` returns the piece of content that the restrictions are applied to.
-   */
-  expand?: string[];
-}
diff --git a/src/api/parameters/getRestrictionsForOperation.ts b/src/api/parameters/getRestrictionsForOperation.ts
deleted file mode 100644
index b2bb58ce..00000000
--- a/src/api/parameters/getRestrictionsForOperation.ts
+++ /dev/null
@@ -1,21 +0,0 @@
-export interface GetRestrictionsForOperation {
-  /** The ID of the content to be queried for its restrictions. */
-  id: string;
-  /** The operation type of the restrictions to be returned. */
-  operationKey: string;
-  /**
-   * A multi-value parameter indicating which properties of the content restrictions to expand.
-   *
-   * - `restrictions.user` returns the piece of content that the restrictions are applied to. Expanded by default.
-   * - `restrictions.group` returns the piece of content that the restrictions are applied to. Expanded by default.
-   * - `content` returns the piece of content that the restrictions are applied to.
-   */
-  expand?: string[];
-  /** The starting index of the users and groups in the returned restrictions. */
-  start?: number;
-  /**
-   * The maximum number of users and the maximum number of groups, in the returned restrictions, to return per page.
-   * Note, this may be restricted by fixed system limits.
-   */
-  limit?: number;
-}
diff --git a/src/api/parameters/getSpace.ts b/src/api/parameters/getSpace.ts
deleted file mode 100644
index 755a78c0..00000000
--- a/src/api/parameters/getSpace.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-export interface GetSpace {
-  /** The key of the space to be returned. */
-  spaceKey: string;
-  /** A multi-value parameter indicating which properties of the content to expand. */
-  expand?: string[];
-}
diff --git a/src/api/parameters/getSpaceContentStates.ts b/src/api/parameters/getSpaceContentStates.ts
deleted file mode 100644
index faea9373..00000000
--- a/src/api/parameters/getSpaceContentStates.ts
+++ /dev/null
@@ -1,4 +0,0 @@
-export interface GetSpaceContentStates {
-  /** The key of the space to be queried for its content state settings. */
-  spaceKey: string;
-}
diff --git a/src/api/parameters/getSpaceProperties.ts b/src/api/parameters/getSpaceProperties.ts
deleted file mode 100644
index a8d2931e..00000000
--- a/src/api/parameters/getSpaceProperties.ts
+++ /dev/null
@@ -1,16 +0,0 @@
-export interface GetSpaceProperties {
-  /** The key of the space to be queried for its properties. */
-  spaceKey: string;
-  /**
-   * A multi-value parameter indicating which properties of the space property to expand. By default, the `version`
-   * object is expanded.
-   *
-   * - `version` returns information about the version of the content.
-   * - `space` returns the space that the properties are in.
-   */
-  expand?: string[];
-  /** The starting index of the returned objects. */
-  start?: number;
-  /** The maximum number of properties to return per page. Note, this may be restricted by fixed system limits. */
-  limit?: number;
-}
diff --git a/src/api/parameters/getSpaceProperty.ts b/src/api/parameters/getSpaceProperty.ts
deleted file mode 100644
index 9d32fc44..00000000
--- a/src/api/parameters/getSpaceProperty.ts
+++ /dev/null
@@ -1,14 +0,0 @@
-export interface GetSpaceProperty {
-  /** The key of the space that the property is in. */
-  spaceKey: string;
-  /** The key of the space property. */
-  key: string;
-  /**
-   * A multi-value parameter indicating which properties of the space property to expand. By default, the `version`
-   * object is expanded.
-   *
-   * - `version` returns information about the version of the content.
-   * - `space` returns the space that the properties are in.
-   */
-  expand?: string[];
-}
diff --git a/src/api/parameters/getSpaceSettings.ts b/src/api/parameters/getSpaceSettings.ts
deleted file mode 100644
index 8f839071..00000000
--- a/src/api/parameters/getSpaceSettings.ts
+++ /dev/null
@@ -1,4 +0,0 @@
-export interface GetSpaceSettings {
-  /** The key of the space to be queried for its settings. */
-  spaceKey: string;
-}
diff --git a/src/api/parameters/getSpaceTheme.ts b/src/api/parameters/getSpaceTheme.ts
deleted file mode 100644
index e8b3b53b..00000000
--- a/src/api/parameters/getSpaceTheme.ts
+++ /dev/null
@@ -1,4 +0,0 @@
-export interface GetSpaceTheme {
-  /** The key of the space to be queried for its theme. */
-  spaceKey: string;
-}
diff --git a/src/api/parameters/getSpaces.ts b/src/api/parameters/getSpaces.ts
deleted file mode 100644
index 3d4f3f9d..00000000
--- a/src/api/parameters/getSpaces.ts
+++ /dev/null
@@ -1,66 +0,0 @@
-export interface GetSpaces {
-  /**
-   * The key of the space to be returned. To return multiple spaces, specify this parameter multiple times with
-   * different values.
-   */
-  spaceKey?: string[];
-  /**
-   * The id of the space to be returned. To return multiple spaces, specify this parameter multiple times with different
-   * values.
-   */
-  spaceId?: number[];
-  /** Filter the results to spaces based on their type. */
-  type?: string;
-  /** Filter the results to spaces based on their status. */
-  status?: string;
-  /** Filter the results to spaces based on their label. */
-  label?: string[];
-  /**
-   * Filter the results to the favourite spaces of the user specified by `favouriteUserKey`. Note, 'favourite' spaces
-   * are also known as 'saved for later' spaces.
-   */
-  favourite?: boolean;
-  /**
-   * The userKey of the user, whose favourite spaces are used to filter the results when using the `favourite`
-   * parameter.
-   *
-   * Leave blank for the current user. Use [Get user](#api-user-get) to get the userKey for a user.
-   */
-  favouriteUserKey?: string;
-  /** A multi-value parameter indicating which properties of the content to expand. */
-  expand?:
-    | 'settings'
-    | 'metadata'
-    | 'metadata.labels'
-    | 'operations'
-    | 'lookAndFeel'
-    | 'permissions'
-    | 'icon'
-    | 'description'
-    | 'description.plain'
-    | 'description.view'
-    | 'theme'
-    | 'homepage'
-    | 'history'
-    | (
-        | 'settings'
-        | 'metadata'
-        | 'metadata.labels'
-        | 'operations'
-        | 'lookAndFeel'
-        | 'permissions'
-        | 'icon'
-        | 'description'
-        | 'description.plain'
-        | 'description.view'
-        | 'theme'
-        | 'homepage'
-        | 'history'
-    )[]
-    | string
-    | string[];
-  /** The starting index of the returned spaces. */
-  start?: number;
-  /** The maximum number of spaces to return per page. Note, this may be restricted by fixed system limits. */
-  limit?: number;
-}
diff --git a/src/api/parameters/getTask.ts b/src/api/parameters/getTask.ts
deleted file mode 100644
index 7fa26aea..00000000
--- a/src/api/parameters/getTask.ts
+++ /dev/null
@@ -1,4 +0,0 @@
-export interface GetTask {
-  /** The ID of the task. */
-  id: string;
-}
diff --git a/src/api/parameters/getTaskById.ts b/src/api/parameters/getTaskById.ts
deleted file mode 100644
index e4434d15..00000000
--- a/src/api/parameters/getTaskById.ts
+++ /dev/null
@@ -1,4 +0,0 @@
-export interface GetTaskById {
-  /** Global ID of the inline task */
-  inlineTaskId: string;
-}
diff --git a/src/api/parameters/getTasks.ts b/src/api/parameters/getTasks.ts
deleted file mode 100644
index 14b63d07..00000000
--- a/src/api/parameters/getTasks.ts
+++ /dev/null
@@ -1,8 +0,0 @@
-export interface GetTasks {
-  /** The key of the tasks. */
-  key?: string;
-  /** The starting index of the returned tasks. */
-  start?: number;
-  /** The maximum number of tasks to return per page. Note, this may be restricted by fixed system limits. */
-  limit?: number;
-}
diff --git a/src/api/parameters/getTheme.ts b/src/api/parameters/getTheme.ts
deleted file mode 100644
index 510a8517..00000000
--- a/src/api/parameters/getTheme.ts
+++ /dev/null
@@ -1,4 +0,0 @@
-export interface GetTheme {
-  /** The key of the theme to be returned. */
-  themeKey: string;
-}
diff --git a/src/api/parameters/getThemes.ts b/src/api/parameters/getThemes.ts
deleted file mode 100644
index fdf2f56d..00000000
--- a/src/api/parameters/getThemes.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-export interface GetThemes {
-  /** The starting index of the returned themes. */
-  start?: number;
-  /** The maximum number of themes to return per page. Note, this may be restricted by fixed system limits. */
-  limit?: number;
-}
diff --git a/src/api/parameters/getUser.ts b/src/api/parameters/getUser.ts
deleted file mode 100644
index 93ac79e9..00000000
--- a/src/api/parameters/getUser.ts
+++ /dev/null
@@ -1,45 +0,0 @@
-export interface GetUser {
-  /**
-   * This parameter is no longer available and will be removed from the documentation soon. Use `accountId` instead. See
-   * the [deprecation notice](/cloud/confluence/deprecation-notice-user-privacy-api-migration-guide/) for details.
-   *
-   * @deprecated Will be removed in next major version.
-   */
-  key?: string;
-  /**
-   * This parameter is no longer available and will be removed from the documentation soon. Use `accountId` instead. See
-   * the [deprecation notice](/cloud/confluence/deprecation-notice-user-privacy-api-migration-guide/) for details.
-   *
-   * @deprecated Will be removed in next major version.
-   */
-  username?: string;
-  /**
-   * The account ID of the user, which uniquely identifies the user across all Atlassian products. For example,
-   * `384093:32b4d9w0-f6a5-3535-11a3-9c8c88d10192`.
-   */
-  accountId: string;
-  /**
-   * A multi-value parameter indicating which properties of the user to expand.
-   *
-   * - `operations` returns the operations that the user is allowed to do.
-   * - `details.personal` returns the 'Personal' details in the user's profile, like the 'Email' and 'Phone'. Note that
-   *   these fields have been deprecated due to privacy changes. See the [migration
-   *   guide](https://developer.atlassian.com/cloud/confluence/deprecation-notice-user-privacy-api-migration-guide/) for
-   *   details.
-   * - `details.business` returns the 'Company' details in the user's profile, like the 'Position' and 'Department'. Note
-   *   that these fields have been deprecated due to privacy changes. See the [migration
-   *   guide](https://developer.atlassian.com/cloud/confluence/deprecation-notice-user-privacy-api-migration-guide/) for
-   *   details.
-   * - `personalSpace` returns the user's personal space, if it exists.
-   * - `isExternalCollaborator` returns whether the user is an external collaborator user
-   */
-  expand?:
-    | 'operations'
-    | 'details.personal'
-    | 'details.business'
-    | 'personalSpace'
-    | 'isExternalCollaborator'
-    | ('operations' | 'details.personal' | 'details.business' | 'personalSpace' | 'isExternalCollaborator')[]
-    | string
-    | string[];
-}
diff --git a/src/api/parameters/getUserProperties.ts b/src/api/parameters/getUserProperties.ts
deleted file mode 100644
index 221d048f..00000000
--- a/src/api/parameters/getUserProperties.ts
+++ /dev/null
@@ -1,8 +0,0 @@
-export interface GetUserProperties {
-  /** The account ID of the user to be queried for its properties. */
-  userId: string;
-  /** The starting index of the returned properties. */
-  start?: number;
-  /** The maximum number of properties to return per page. Note, this may be restricted by fixed system limits. */
-  limit?: number;
-}
diff --git a/src/api/parameters/getUserProperty.ts b/src/api/parameters/getUserProperty.ts
deleted file mode 100644
index de07e55d..00000000
--- a/src/api/parameters/getUserProperty.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-export interface GetUserProperty {
-  /** The account ID of the user to be queried for its properties. */
-  userId: string;
-  /** The key of the user property. */
-  key: string;
-}
diff --git a/src/api/parameters/getViewers.ts b/src/api/parameters/getViewers.ts
deleted file mode 100644
index 5be1ce0f..00000000
--- a/src/api/parameters/getViewers.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-export interface GetViewers {
-  /** The ID of the content to get the viewers for. */
-  contentId: string;
-  /** The number of views for the content since the date. */
-  fromDate?: string;
-}
diff --git a/src/api/parameters/getViews.ts b/src/api/parameters/getViews.ts
deleted file mode 100644
index 5048ec64..00000000
--- a/src/api/parameters/getViews.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-export interface GetViews {
-  /** The ID of the content to get the views for. */
-  contentId: string;
-  /** The number of views for the content since the date. */
-  fromDate?: string;
-}
diff --git a/src/api/parameters/getWatchersForSpace.ts b/src/api/parameters/getWatchersForSpace.ts
deleted file mode 100644
index 1ab6f928..00000000
--- a/src/api/parameters/getWatchersForSpace.ts
+++ /dev/null
@@ -1,8 +0,0 @@
-export interface GetWatchersForSpace {
-  /** The key of the space to get watchers. */
-  spaceKey: string;
-  /** The start point of the collection to return. */
-  start?: string;
-  /** The limit of the number of items to return, this may be restricted by fixed system limits. */
-  limit?: string;
-}
diff --git a/src/api/parameters/getWatchesForPage.ts b/src/api/parameters/getWatchesForPage.ts
deleted file mode 100644
index ac9f6a6d..00000000
--- a/src/api/parameters/getWatchesForPage.ts
+++ /dev/null
@@ -1,8 +0,0 @@
-export interface GetWatchesForPage {
-  /** The ID of the content to be queried for its watches. */
-  id: string;
-  /** The starting index of the returned watches. */
-  start?: number;
-  /** The maximum number of watches to return per page. Note, this may be restricted by fixed system limits. */
-  limit?: number;
-}
diff --git a/src/api/parameters/getWatchesForSpace.ts b/src/api/parameters/getWatchesForSpace.ts
deleted file mode 100644
index a16c9181..00000000
--- a/src/api/parameters/getWatchesForSpace.ts
+++ /dev/null
@@ -1,8 +0,0 @@
-export interface GetWatchesForSpace {
-  /** The ID of the content to be queried for its watches. */
-  id: string;
-  /** The starting index of the returned watches. */
-  start?: number;
-  /** The maximum number of watches to return per page. Note, this may be restricted by fixed system limits. */
-  limit?: number;
-}
diff --git a/src/api/parameters/index.ts b/src/api/parameters/index.ts
deleted file mode 100644
index 5e9a0d02..00000000
--- a/src/api/parameters/index.ts
+++ /dev/null
@@ -1,170 +0,0 @@
-export * from './addContentWatcher';
-export * from './addCustomContentPermissions';
-export * from './addGroupToContentRestriction';
-export * from './addGroupToContentRestrictionByGroupId';
-export * from './addLabelsToContent';
-export * from './addLabelsToSpace';
-export * from './addLabelWatcher';
-export * from './addPermissionToSpace';
-export * from './addRestrictions';
-export * from './addSpaceWatcher';
-export * from './addUserToContentRestriction';
-export * from './addUserToGroup';
-export * from './addUserToGroupByGroupId';
-export * from './archivePages';
-export * from './asyncConvertContentBodyRequest';
-export * from './asyncConvertContentBodyResponse';
-export * from './bulkAsyncConvertContentBodyRequest';
-export * from './bulkAsyncConvertContentBodyResponse';
-export * from './checkContentPermission';
-export * from './convertContentBody';
-export * from './copyPage';
-export * from './copyPageHierarchy';
-export * from './createAttachments';
-export * from './createAuditRecord';
-export * from './createContent';
-export * from './createContentProperty';
-export * from './createContentPropertyForKey';
-export * from './createContentTemplate';
-export * from './createGroup';
-export * from './createOrUpdateAttachments';
-export * from './createPrivateSpace';
-export * from './createRelationship';
-export * from './createSpace';
-export * from './createSpaceProperty';
-export * from './createSpacePropertyForKey';
-export * from './createUserProperty';
-export * from './deleteContent';
-export * from './deleteContentProperty';
-export * from './deleteContentVersion';
-export * from './deleteGroupById';
-export * from './deleteLabelFromSpace';
-export * from './deletePageTree';
-export * from './deleteRelationship';
-export * from './deleteRestrictions';
-export * from './deleteSpace';
-export * from './deleteSpaceProperty';
-export * from './deleteUserProperty';
-export * from './downloadAttachment';
-export * from './exportAuditRecords';
-export * from './findSourcesForTarget';
-export * from './findTargetFromSource';
-export * from './getAllLabelContent';
-export * from './getAndAsyncConvertMacroBodyByMacroId';
-export * from './getAndConvertMacroBodyByMacroId';
-export * from './getAnonymousUser';
-export * from './getAttachments';
-export * from './getAuditRecords';
-export * from './getAuditRecordsForTimePeriod';
-export * from './getAvailableContentStates';
-export * from './getBlueprintTemplates';
-export * from './getBulkUserLookup';
-export * from './getBulkUserMigration';
-export * from './getContent';
-export * from './getContentById';
-export * from './getContentByTypeForSpace';
-export * from './getContentChildren';
-export * from './getContentChildrenByType';
-export * from './getContentComments';
-export * from './getContentDescendants';
-export * from './getContentForSpace';
-export * from './getContentProperties';
-export * from './getContentProperty';
-export * from './getContentRestrictionStatusForGroup';
-export * from './getContentRestrictionStatusForUser';
-export * from './getContentState';
-export * from './getContentStateSettings';
-export * from './getContentsWithState';
-export * from './getContentTemplate';
-export * from './getContentTemplates';
-export * from './getContentVersion';
-export * from './getContentVersions';
-export * from './getContentWatchStatus';
-export * from './getCurrentUser';
-export * from './getDescendantsOfType';
-export * from './getGroupByGroupId';
-export * from './getGroupByName';
-export * from './getGroupByQueryParam';
-export * from './getGroupMembers';
-export * from './getGroupMembersByGroupId';
-export * from './getGroupMembershipsForUser';
-export * from './getGroups';
-export * from './getHistoryForContent';
-export * from './getIndividualGroupRestrictionStatusByGroupId';
-export * from './getLabelsForContent';
-export * from './getLabelsForSpace';
-export * from './getLookAndFeelSettings';
-export * from './getMacroBodyByMacroId';
-export * from './getMembersByQueryParam';
-export * from './getPrivacyUnsafeUserEmail';
-export * from './getPrivacyUnsafeUserEmailBulk';
-export * from './getRelationship';
-export * from './getRestrictions';
-export * from './getRestrictionsByOperation';
-export * from './getRestrictionsForOperation';
-export * from './getSpace';
-export * from './getSpaceContentStates';
-export * from './getSpaceProperties';
-export * from './getSpaceProperty';
-export * from './getSpaces';
-export * from './getSpaceSettings';
-export * from './getSpaceTheme';
-export * from './getTask';
-export * from './getTaskById';
-export * from './getTasks';
-export * from './getTheme';
-export * from './getThemes';
-export * from './getUser';
-export * from './getUserProperties';
-export * from './getUserProperty';
-export * from './getViewers';
-export * from './getViews';
-export * from './getWatchersForSpace';
-export * from './getWatchesForPage';
-export * from './getWatchesForSpace';
-export * from './isWatchingLabel';
-export * from './isWatchingSpace';
-export * from './movePage';
-export * from './publishLegacyDraft';
-export * from './publishSharedDraft';
-export * from './registerModules';
-export * from './removeContentState';
-export * from './removeContentWatcher';
-export * from './removeGroup';
-export * from './removeGroupById';
-export * from './removeGroupByName';
-export * from './removeLabelFromContent';
-export * from './removeLabelFromContentUsingQueryParameter';
-export * from './removeLabelWatcher';
-export * from './removeMemberFromGroup';
-export * from './removeMemberFromGroupByGroupId';
-export * from './removeModules';
-export * from './removePermission';
-export * from './removeSpaceWatch';
-export * from './removeTemplate';
-export * from './removeUserFromContentRestriction';
-export * from './resetLookAndFeelSettings';
-export * from './resetSpaceTheme';
-export * from './restoreContentVersion';
-export * from './searchByCQL';
-export * from './searchContentByCQL';
-export * from './searchGroups';
-export * from './searchTasks';
-export * from './searchUser';
-export * from './setContentState';
-export * from './setLookAndFeelSettings';
-export * from './setRetentionPeriod';
-export * from './setSpaceTheme';
-export * from './updateAttachmentData';
-export * from './updateAttachmentProperties';
-export * from './updateContent';
-export * from './updateContentProperty';
-export * from './updateContentTemplate';
-export * from './updateLookAndFeel';
-export * from './updateLookAndFeelSettings';
-export * from './updateRestrictions';
-export * from './updateSpace';
-export * from './updateSpaceProperty';
-export * from './updateSpaceSettings';
-export * from './updateTaskById';
-export * from './updateUserProperty';
diff --git a/src/api/parameters/isWatchingLabel.ts b/src/api/parameters/isWatchingLabel.ts
deleted file mode 100644
index 2899fe4e..00000000
--- a/src/api/parameters/isWatchingLabel.ts
+++ /dev/null
@@ -1,19 +0,0 @@
-export interface IsWatchingLabel {
-  /** The name of the label to be queried for whether the specified user is watching it. */
-  labelName: string;
-  /**
-   * This parameter is no longer available and will be removed from the documentation soon. Use `accountId` instead. See
-   * the [deprecation notice](/cloud/confluence/deprecation-notice-user-privacy-api-migration-guide/) for details.
-   */
-  key?: string;
-  /**
-   * This parameter is no longer available and will be removed from the documentation soon. Use `accountId` instead. See
-   * the [deprecation notice](/cloud/confluence/deprecation-notice-user-privacy-api-migration-guide/) for details.
-   */
-  username?: string;
-  /**
-   * The `accountId` of the user to be queried for whether they are watching the label. The accountId uniquely
-   * identifies the user across all Atlassian products. For example, `384093:32b4d9w0-f6a5-3535-11a3-9c8c88d10192`.
-   */
-  accountId: string;
-}
diff --git a/src/api/parameters/isWatchingSpace.ts b/src/api/parameters/isWatchingSpace.ts
deleted file mode 100644
index 0936a299..00000000
--- a/src/api/parameters/isWatchingSpace.ts
+++ /dev/null
@@ -1,19 +0,0 @@
-export interface IsWatchingSpace {
-  /** The key of the space to be queried for whether the specified user is watching it. */
-  spaceKey: string;
-  /**
-   * This parameter is no longer available and will be removed from the documentation soon. Use `accountId` instead. See
-   * the [deprecation notice](/cloud/confluence/deprecation-notice-user-privacy-api-migration-guide/) for details.
-   */
-  key?: string;
-  /**
-   * This parameter is no longer available and will be removed from the documentation soon. Use `accountId` instead. See
-   * the [deprecation notice](/cloud/confluence/deprecation-notice-user-privacy-api-migration-guide/) for details.
-   */
-  username?: string;
-  /**
-   * The `accountId` of the user to be queried for whether they are watching the space. The accountId uniquely
-   * identifies the user across all Atlassian products. For example, `384093:32b4d9w0-f6a5-3535-11a3-9c8c88d10192`.
-   */
-  accountId: string;
-}
diff --git a/src/api/parameters/movePage.ts b/src/api/parameters/movePage.ts
deleted file mode 100644
index 49f3efb6..00000000
--- a/src/api/parameters/movePage.ts
+++ /dev/null
@@ -1,14 +0,0 @@
-export interface MovePage {
-  /** The ID of the page to be moved */
-  pageId?: string;
-  /**
-   * The position to move the page to relative to the target page:
-   *
-   * - `before` - move the page under the same parent as the target, before the target in the list of children
-   * - `after` - move the page under the same parent as the target, after the target in the list of children
-   * - `append` - move the page to be a child of the target
-   */
-  position: 'before' | 'after' | 'append' | string;
-  /** The ID of the target page for this operation */
-  targetId: string;
-}
diff --git a/src/api/parameters/publishLegacyDraft.ts b/src/api/parameters/publishLegacyDraft.ts
deleted file mode 100644
index 81363275..00000000
--- a/src/api/parameters/publishLegacyDraft.ts
+++ /dev/null
@@ -1,17 +0,0 @@
-import type { ContentBlueprintDraft } from '../models';
-
-export interface PublishLegacyDraft extends ContentBlueprintDraft {
-  /**
-   * The ID of the draft page that was created from a blueprint. You can find the `draftId` in the Confluence
-   * application by opening the draft page and checking the page URL.
-   */
-  draftId: string;
-  /**
-   * The status of the content to be updated, i.e. the draft. This is set to 'draft' by default, so you shouldn't need
-   * to specify it.
-   */
-  status?: string;
-  /** A multi-value parameter indicating which properties of the content to expand. */
-  expand?: string[];
-  bodyStatus?: string;
-}
diff --git a/src/api/parameters/publishSharedDraft.ts b/src/api/parameters/publishSharedDraft.ts
deleted file mode 100644
index d49acbf9..00000000
--- a/src/api/parameters/publishSharedDraft.ts
+++ /dev/null
@@ -1,17 +0,0 @@
-import type { ContentBlueprintDraft } from '../models';
-
-export interface PublishSharedDraft extends ContentBlueprintDraft {
-  /**
-   * The ID of the draft page that was created from a blueprint. You can find the `draftId` in the Confluence
-   * application by opening the draft page and checking the page URL.
-   */
-  draftId: string;
-  /**
-   * The status of the content to be updated, i.e. the draft. This is set to 'draft' by default, so you shouldn't need
-   * to specify it.
-   */
-  status?: string;
-  /** A multi-value parameter indicating which properties of the content to expand. */
-  expand?: string[];
-  bodyStatus?: string;
-}
diff --git a/src/api/parameters/registerModules.ts b/src/api/parameters/registerModules.ts
deleted file mode 100644
index eab884dc..00000000
--- a/src/api/parameters/registerModules.ts
+++ /dev/null
@@ -1,3 +0,0 @@
-import type { ConnectModules } from '../models';
-
-export type RegisterModules = ConnectModules;
diff --git a/src/api/parameters/removeContentState.ts b/src/api/parameters/removeContentState.ts
deleted file mode 100644
index 002037bf..00000000
--- a/src/api/parameters/removeContentState.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-export interface RemoveContentState {
-  /** The Id of the content whose content state is to be set. */
-  id?: string;
-  /** Status of content state from which to delete state. Can be draft or archived */
-  status?: string;
-}
diff --git a/src/api/parameters/removeContentWatcher.ts b/src/api/parameters/removeContentWatcher.ts
deleted file mode 100644
index 24ca7db9..00000000
--- a/src/api/parameters/removeContentWatcher.ts
+++ /dev/null
@@ -1,21 +0,0 @@
-export interface RemoveContentWatcher {
-  /** Note, you must add header when making a request, as this operation has XSRF protection. */
-  'X-Atlassian-Token': string;
-  /** The ID of the content to remove the watcher from. */
-  contentId: string;
-  /**
-   * This parameter is no longer available and will be removed from the documentation soon. Use `accountId` instead. See
-   * the [deprecation notice](/cloud/confluence/deprecation-notice-user-privacy-api-migration-guide/) for details.
-   */
-  key?: string;
-  /**
-   * This parameter is no longer available and will be removed from the documentation soon. Use `accountId` instead. See
-   * the [deprecation notice](/cloud/confluence/deprecation-notice-user-privacy-api-migration-guide/) for details.
-   */
-  username?: string;
-  /**
-   * The `accountId` of the user to be removed as a watcher. The accountId uniquely identifies the user across all
-   * Atlassian products. For example, `384093:32b4d9w0-f6a5-3535-11a3-9c8c88d10192`.
-   */
-  accountId: string;
-}
diff --git a/src/api/parameters/removeGroup.ts b/src/api/parameters/removeGroup.ts
deleted file mode 100644
index 6b404364..00000000
--- a/src/api/parameters/removeGroup.ts
+++ /dev/null
@@ -1,4 +0,0 @@
-export interface RemoveGroup {
-  /** Name of the group to delete. */
-  name: string;
-}
diff --git a/src/api/parameters/removeGroupById.ts b/src/api/parameters/removeGroupById.ts
deleted file mode 100644
index ce40bf0c..00000000
--- a/src/api/parameters/removeGroupById.ts
+++ /dev/null
@@ -1,14 +0,0 @@
-export interface RemoveGroupById {
-  /** The ID of the content that the restriction applies to. */
-  id: string;
-  /**
-   * The operation that the restriction applies to.
-   *
-   * @example
-   *   'read';
-   *   'update';
-   */
-  operationKey: string;
-  /** The id of the group to remove from the content restriction. */
-  groupId: string;
-}
diff --git a/src/api/parameters/removeGroupByName.ts b/src/api/parameters/removeGroupByName.ts
deleted file mode 100644
index afded5ae..00000000
--- a/src/api/parameters/removeGroupByName.ts
+++ /dev/null
@@ -1,14 +0,0 @@
-export interface RemoveGroupByName {
-  /** The ID of the content that the restriction applies to. */
-  id: string;
-  /**
-   * The operation that the restriction applies to.
-   *
-   * @example
-   *   'read';
-   *   'update';
-   */
-  operationKey: string;
-  /** The name of the group to remove from the content restriction. */
-  groupName: string;
-}
diff --git a/src/api/parameters/removeLabelFromContent.ts b/src/api/parameters/removeLabelFromContent.ts
deleted file mode 100644
index 5749e8ed..00000000
--- a/src/api/parameters/removeLabelFromContent.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-export interface RemoveLabelFromContent {
-  /** The ID of the content that the label will be removed from. */
-  id: string;
-  /** The name of the label to be removed. */
-  label: string;
-}
diff --git a/src/api/parameters/removeLabelFromContentUsingQueryParameter.ts b/src/api/parameters/removeLabelFromContentUsingQueryParameter.ts
deleted file mode 100644
index 96813c5f..00000000
--- a/src/api/parameters/removeLabelFromContentUsingQueryParameter.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-export interface RemoveLabelFromContentUsingQueryParameter {
-  /** The ID of the content that the label will be removed from. */
-  id: string;
-  /** The name of the label to be removed. */
-  name: string;
-}
diff --git a/src/api/parameters/removeLabelWatcher.ts b/src/api/parameters/removeLabelWatcher.ts
deleted file mode 100644
index 47d276e1..00000000
--- a/src/api/parameters/removeLabelWatcher.ts
+++ /dev/null
@@ -1,19 +0,0 @@
-export interface RemoveLabelWatcher {
-  /** The name of the label to remove the watcher from. */
-  labelName: string;
-  /**
-   * This parameter is no longer available and will be removed from the documentation soon. Use `accountId` instead. See
-   * the [deprecation notice](/cloud/confluence/deprecation-notice-user-privacy-api-migration-guide/) for details.
-   */
-  key?: string;
-  /**
-   * This parameter is no longer available and will be removed from the documentation soon. Use `accountId` instead. See
-   * the [deprecation notice](/cloud/confluence/deprecation-notice-user-privacy-api-migration-guide/) for details.
-   */
-  username?: string;
-  /**
-   * The `accountId` of the user to be removed as a watcher. The accountId uniquely identifies the user across all
-   * Atlassian products. For example, `384093:32b4d9w0-f6a5-3535-11a3-9c8c88d10192`.
-   */
-  accountId: string;
-}
diff --git a/src/api/parameters/removeMemberFromGroup.ts b/src/api/parameters/removeMemberFromGroup.ts
deleted file mode 100644
index 29eec074..00000000
--- a/src/api/parameters/removeMemberFromGroup.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-export interface RemoveMemberFromGroup {
-  /** Name of the group whose membership is updated. */
-  name: string;
-  /** AccountId of the user whose membership is removed. */
-  accountId: string;
-}
diff --git a/src/api/parameters/removeMemberFromGroupByGroupId.ts b/src/api/parameters/removeMemberFromGroupByGroupId.ts
deleted file mode 100644
index 12e886ce..00000000
--- a/src/api/parameters/removeMemberFromGroupByGroupId.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-export interface RemoveMemberFromGroupByGroupId {
-  /** Id of the group whose membership is updated. */
-  groupId: string;
-  /** AccountId of the user whose membership is removed. */
-  accountId: string;
-}
diff --git a/src/api/parameters/removeModules.ts b/src/api/parameters/removeModules.ts
deleted file mode 100644
index 410214ec..00000000
--- a/src/api/parameters/removeModules.ts
+++ /dev/null
@@ -1,8 +0,0 @@
-export interface RemoveModules {
-  /**
-   * The key of the module to remove. To include multiple module keys, provide multiple copies of this parameter. For
-   * example, `moduleKey=dynamic-attachment-entity-property&moduleKey=dynamic-select-field`. Nonexistent keys are
-   * ignored.
-   */
-  moduleKey: string[];
-}
diff --git a/src/api/parameters/removePermission.ts b/src/api/parameters/removePermission.ts
deleted file mode 100644
index e192ad2e..00000000
--- a/src/api/parameters/removePermission.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-export interface RemovePermission {
-  /** The key of the space to be queried for its content. */
-  spaceKey: string;
-  /** Id of the permission to be deleted. */
-  id: number;
-}
diff --git a/src/api/parameters/removeSpaceWatch.ts b/src/api/parameters/removeSpaceWatch.ts
deleted file mode 100644
index 00d28b29..00000000
--- a/src/api/parameters/removeSpaceWatch.ts
+++ /dev/null
@@ -1,19 +0,0 @@
-export interface RemoveSpaceWatch {
-  /** The key of the space to remove the watcher from. */
-  spaceKey: string;
-  /**
-   * This parameter is no longer available and will be removed from the documentation soon. Use `accountId` instead. See
-   * the [deprecation notice](/cloud/confluence/deprecation-notice-user-privacy-api-migration-guide/) for details.
-   */
-  key?: string;
-  /**
-   * This parameter is no longer available and will be removed from the documentation soon. Use `accountId` instead. See
-   * the [deprecation notice](/cloud/confluence/deprecation-notice-user-privacy-api-migration-guide/) for details.
-   */
-  username?: string;
-  /**
-   * The `accountId` of the user to be removed as a watcher. The accountId uniquely identifies the user across all
-   * Atlassian products. For example, `384093:32b4d9w0-f6a5-3535-11a3-9c8c88d10192`.
-   */
-  accountId: string;
-}
diff --git a/src/api/parameters/removeTemplate.ts b/src/api/parameters/removeTemplate.ts
deleted file mode 100644
index 7de87f53..00000000
--- a/src/api/parameters/removeTemplate.ts
+++ /dev/null
@@ -1,4 +0,0 @@
-export interface RemoveTemplate {
-  /** The ID of the template to be deleted. */
-  contentTemplateId: string;
-}
diff --git a/src/api/parameters/removeUserFromContentRestriction.ts b/src/api/parameters/removeUserFromContentRestriction.ts
deleted file mode 100644
index 9f608d86..00000000
--- a/src/api/parameters/removeUserFromContentRestriction.ts
+++ /dev/null
@@ -1,21 +0,0 @@
-export interface RemoveUserFromContentRestriction {
-  /** The ID of the content that the restriction applies to. */
-  id: string;
-  /** The operation that the restriction applies to. */
-  operationKey: string;
-  /**
-   * This parameter is no longer available and will be removed from the documentation soon. Use `accountId` instead. See
-   * the [deprecation notice](/cloud/confluence/deprecation-notice-user-privacy-api-migration-guide/) for details.
-   */
-  key?: string;
-  /**
-   * This parameter is no longer available and will be removed from the documentation soon. Use `accountId` instead. See
-   * the [deprecation notice](/cloud/confluence/deprecation-notice-user-privacy-api-migration-guide/) for details.
-   */
-  userName?: string;
-  /**
-   * The account ID of the user to remove from the content restriction. The accountId uniquely identifies the user
-   * across all Atlassian products. For example, `384093:32b4d9w0-f6a5-3535-11a3-9c8c88d10192`.
-   */
-  accountId: string;
-}
diff --git a/src/api/parameters/resetLookAndFeelSettings.ts b/src/api/parameters/resetLookAndFeelSettings.ts
deleted file mode 100644
index f948420a..00000000
--- a/src/api/parameters/resetLookAndFeelSettings.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-export interface ResetLookAndFeelSettings {
-  /**
-   * The key of the space for which the look and feel settings will be reset. If this is not set, the global look and
-   * feel settings will be reset.
-   */
-  spaceKey?: string;
-}
diff --git a/src/api/parameters/resetSpaceTheme.ts b/src/api/parameters/resetSpaceTheme.ts
deleted file mode 100644
index 606ae43f..00000000
--- a/src/api/parameters/resetSpaceTheme.ts
+++ /dev/null
@@ -1,4 +0,0 @@
-export interface ResetSpaceTheme {
-  /** The key of the space to reset the theme for. */
-  spaceKey: string;
-}
diff --git a/src/api/parameters/restoreContentVersion.ts b/src/api/parameters/restoreContentVersion.ts
deleted file mode 100644
index 5ba0e064..00000000
--- a/src/api/parameters/restoreContentVersion.ts
+++ /dev/null
@@ -1,14 +0,0 @@
-import type { VersionRestore } from '../models';
-
-export interface RestoreContentVersion extends VersionRestore {
-  /** The ID of the content for which the history will be restored. */
-  id: string;
-  /**
-   * A multi-value parameter indicating which properties of the content to expand. By default, the `content` object is
-   * expanded.
-   *
-   * - `collaborators` returns the users that collaborated on the version.
-   * - `content` returns the content for the version.
-   */
-  expand?: string[];
-}
diff --git a/src/api/parameters/searchByCQL.ts b/src/api/parameters/searchByCQL.ts
deleted file mode 100644
index 6304988a..00000000
--- a/src/api/parameters/searchByCQL.ts
+++ /dev/null
@@ -1,34 +0,0 @@
-export interface SearchByCQL {
-  /**
-   * The CQL query to be used for the search. See [Advanced Searching using
-   * CQL](https://developer.atlassian.com/cloud/confluence/advanced-searching-using-cql/) for instructions on how to
-   * build a CQL query.
-   */
-  cql: string;
-  /**
-   * The space, content, and content status to execute the search against.
-   *
-   * - `spaceKey` Key of the space to search against. Optional.
-   * - `contentId` ID of the content to search against. Optional. Must be in the space specified by `spaceKey`.
-   * - `contentStatuses` Content statuses to search against. Optional.
-   *
-   * Specify these values in an object. For example, `cqlcontext={%22spaceKey%22:%22TEST%22, %22contentId%22:%22123%22}`
-   */
-  cqlcontext?: string;
-  /** Pointer to a set of search results, returned as part of the `next` or `prev` URL from the previous search call. */
-  cursor?: string;
-  next?: boolean;
-  prev?: boolean;
-  /** The maximum number of content objects to return per page. Note, this may be restricted by fixed system limits. */
-  limit?: number;
-  /** The start point of the collection to return */
-  start?: number;
-  /** Whether to include content from archived spaces in the results. */
-  includeArchivedSpaces?: boolean;
-  /** Whether to exclude current spaces and only show archived spaces. */
-  excludeCurrentSpaces?: boolean;
-  /** The excerpt strategy to apply to the result */
-  excerpt?: string;
-  sitePermissionTypeFilter?: string;
-  expand?: string[];
-}
diff --git a/src/api/parameters/searchContentByCQL.ts b/src/api/parameters/searchContentByCQL.ts
deleted file mode 100644
index 5c224f86..00000000
--- a/src/api/parameters/searchContentByCQL.ts
+++ /dev/null
@@ -1,19 +0,0 @@
-export interface SearchContentByCQL {
-  /** The CQL string that is used to find the requested content. */
-  cql: string;
-  /**
-   * The space, content, and content status to execute the search against. Specify this as an object with the following
-   * properties:
-   *
-   * - `spaceKey` Key of the space to search against. Optional.
-   * - `contentId` ID of the content to search against. Optional. Must be in the space spacified by `spaceKey`.
-   * - `contentStatuses` Content statuses to search against. Optional.
-   */
-  cqlcontext?: string;
-  /** A multi-value parameter indicating which properties of the content to expand. */
-  expand?: string[];
-  /** Pointer to a set of search results, returned as part of the `next` or `prev` URL from the previous search call. */
-  cursor?: string;
-  /** The maximum number of content objects to return per page. Note, this may be restricted by fixed system limits. */
-  limit?: number;
-}
diff --git a/src/api/parameters/searchGroups.ts b/src/api/parameters/searchGroups.ts
deleted file mode 100644
index 55dd4b0b..00000000
--- a/src/api/parameters/searchGroups.ts
+++ /dev/null
@@ -1,13 +0,0 @@
-export interface SearchGroups {
-  /** The search term used to query results. */
-  query: string;
-  /** The starting index of the returned groups. */
-  start?: number;
-  /** The maximum number of groups to return per page. Note, this is restricted to a maximum limit of 200 groups. */
-  limit?: number;
-  /**
-   * Whether to include total size parameter in the results. Note, fetching total size property is an expensive
-   * operation; use it if your use case needs this value.
-   */
-  shouldReturnTotalSize?: boolean;
-}
diff --git a/src/api/parameters/searchTasks.ts b/src/api/parameters/searchTasks.ts
deleted file mode 100644
index ffc2da17..00000000
--- a/src/api/parameters/searchTasks.ts
+++ /dev/null
@@ -1,30 +0,0 @@
-export interface SearchTasks {
-  /** The starting offset for the results. */
-  start?: number;
-  /** The number of results to be returned. */
-  limit?: number;
-  /** The space key of a space. Multiple space keys can be specified. */
-  spaceKey?: string;
-  /** The page id of a page. Multiple page ids can be specified. */
-  pageId?: string;
-  /** Account ID of a user to whom a task is assigned. Multiple users can be specified. */
-  assignee?: string;
-  /** Account ID of a user to who created a task. Multiple users can be specified. */
-  creator?: string;
-  /** Account ID of a user who completed a task. Multiple users can be specified. */
-  completedUser?: string;
-  /** Start of date range based on due dates (inclusive). */
-  duedateFrom?: number;
-  /** End of date range based on due dates (inclusive). */
-  duedateTo?: number;
-  /** Start of date range based on create dates (inclusive). */
-  createdateFrom?: number;
-  /** End of date range based on create dates (inclusive). */
-  createdateTo?: number;
-  /** Start of date range based on complete dates (inclusive). */
-  completedateFrom?: number;
-  /** End of date range based on complete dates (inclusive). */
-  completedateTo?: number;
-  /** The status of the task. (checked/unchecked) */
-  status?: string;
-}
diff --git a/src/api/parameters/searchUser.ts b/src/api/parameters/searchUser.ts
deleted file mode 100644
index b646bfd5..00000000
--- a/src/api/parameters/searchUser.ts
+++ /dev/null
@@ -1,34 +0,0 @@
-export interface SearchUser {
-  /**
-   * The CQL query to be used for the search. See [Advanced Searching using
-   * CQL](https://developer.atlassian.com/cloud/confluence/advanced-searching-using-cql/) for instructions on how to
-   * build a CQL query.
-   *
-   *     Example queries:
-   *       - cql=type=user will return all users
-   *       - cql=user=“1234” will return user with accountId “1234”
-   *       - You can also use IN, NOT IN, != operators
-   *       - cql=user IN (“12”, “34") will return users with accountids “12” and “34”
-   *       - cql=user.fullname~jo will return users with nickname/full name starting with “jo”
-   *       - cql=user.accountid=“123” will return user with accountId “123”
-   */
-  cql: string;
-  /** The starting index of the returned users. */
-  start?: number;
-  /** The maximum number of user objects to return per page. Note, this may be restricted by fixed system limits. */
-  limit?: number;
-  /**
-   * A multi-value parameter indicating which properties of the user to expand.
-   *
-   * - `operations` returns the operations for the user, which are used when setting permissions.
-   * - `personalSpace` returns the personal space of the user.
-   */
-  expand?: string[];
-  /**
-   * Filters users by permission type. Use `none` to default to licensed users, `externalCollaborator` for
-   * external/guest users, and `all` to include all permission types.
-   *
-   * @default none
-   */
-  sitePermissionTypeFilter?: 'all' | 'externalCollaborator' | 'none' | string;
-}
diff --git a/src/api/parameters/setContentState.ts b/src/api/parameters/setContentState.ts
deleted file mode 100644
index b690926a..00000000
--- a/src/api/parameters/setContentState.ts
+++ /dev/null
@@ -1,11 +0,0 @@
-import type { ContentStateRestInput } from '../models';
-
-export interface SetContentState extends ContentStateRestInput {
-  /** The Id of the content whose content state is to be set. */
-  id?: string;
-  /**
-   * Status of content onto which state will be placed. If draft, then draft state will change. If current, state will
-   * be placed onto a new version of the content with same body as previous version.
-   */
-  status?: 'current' | 'draft' | string;
-}
diff --git a/src/api/parameters/setLookAndFeelSettings.ts b/src/api/parameters/setLookAndFeelSettings.ts
deleted file mode 100644
index 6273053a..00000000
--- a/src/api/parameters/setLookAndFeelSettings.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-export interface SetLookAndFeelSettings {
-  /**
-   * The key of the space for which the look and feel settings will be set. If this is not set, the global look and feel
-   * settings will be set.
-   */
-  spaceKey?: string;
-}
diff --git a/src/api/parameters/setRetentionPeriod.ts b/src/api/parameters/setRetentionPeriod.ts
deleted file mode 100644
index 63017408..00000000
--- a/src/api/parameters/setRetentionPeriod.ts
+++ /dev/null
@@ -1,3 +0,0 @@
-import type { RetentionPeriod } from '../models';
-
-export interface SetRetentionPeriod extends RetentionPeriod {}
diff --git a/src/api/parameters/setSpaceTheme.ts b/src/api/parameters/setSpaceTheme.ts
deleted file mode 100644
index 5dbe0346..00000000
--- a/src/api/parameters/setSpaceTheme.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-import type { ThemeUpdate } from '../models';
-
-export interface SetSpaceTheme extends ThemeUpdate {
-  /** The key of the space to set the theme for. */
-  spaceKey: string;
-}
diff --git a/src/api/parameters/updateAttachmentData.ts b/src/api/parameters/updateAttachmentData.ts
deleted file mode 100644
index 8c71db1a..00000000
--- a/src/api/parameters/updateAttachmentData.ts
+++ /dev/null
@@ -1,12 +0,0 @@
-import type { CreateAttachments } from './createAttachments';
-import type { ExtractBaseType } from '~/interfaces';
-
-export interface UpdateAttachmentData {
-  /** The ID of the content that the attachment is attached to. */
-  id: string;
-  /** The ID of the attachment to update. */
-  attachmentId: string;
-
-  /** Attachment data to update. */
-  attachment: ExtractBaseType;
-}
diff --git a/src/api/parameters/updateAttachmentProperties.ts b/src/api/parameters/updateAttachmentProperties.ts
deleted file mode 100644
index 571666a6..00000000
--- a/src/api/parameters/updateAttachmentProperties.ts
+++ /dev/null
@@ -1,58 +0,0 @@
-/* eslint-disable @typescript-eslint/no-explicit-any */
-import type {
-  AttachmentMetadata,
-  Container,
-  Content,
-  ContentChildren,
-  ContentChildType,
-  ContentHistory,
-  GenericLinks,
-  OperationCheckResult,
-  Space,
-  Version,
-} from '../models';
-
-export interface UpdateAttachmentProperties {
-  /** The ID of the content that the attachment is attached to. */
-  id: string;
-  /** The ID of the attachment to update. */
-  attachmentId: string;
-  update: Record & {
-    id: string;
-    type: 'page' | 'blogpost' | 'attachment' | 'content' | string;
-    status: 'current' | 'draft' | string;
-    title?: string;
-    space?: Space;
-    history?: ContentHistory;
-    version: Partial;
-    ancestors?: Content[];
-    operations?: OperationCheckResult[];
-    children?: ContentChildren;
-    childTypes?: ContentChildType;
-    descendants?: ContentChildren;
-    container?: Container;
-    body?: any;
-    restrictions?: any;
-    metadata?: Partial;
-    macroRenderedOutput?: any;
-    extensions?: any;
-    _expandable?: {
-      childTypes: string;
-      container: string;
-      metadata: string;
-      operations: string;
-      children: string;
-      restrictions: string;
-      history: string;
-      ancestors: string;
-      body: string;
-      version: string;
-      descendants: string;
-      space: string;
-      extensions: string;
-      schedulePublishDate: string;
-      macroRenderedOutput: string;
-    };
-    _links?: GenericLinks;
-  };
-}
diff --git a/src/api/parameters/updateContent.ts b/src/api/parameters/updateContent.ts
deleted file mode 100644
index a5b2ed89..00000000
--- a/src/api/parameters/updateContent.ts
+++ /dev/null
@@ -1,21 +0,0 @@
-import type { ContentUpdate } from '../models';
-
-export interface UpdateContent extends ContentUpdate {
-  /** The ID of the content to be updated. */
-  id: string;
-
-  /**
-   * The updated status of the content. Use this parameter to change the status of a piece of content without passing
-   * the entire request body.
-   */
-  status?: 'current' | 'trashed' | 'historical' | 'draft' | string;
-
-  /** The action that should be taken when conflicts are discovered. Only used when publishing a draft page. */
-  conflictPolicy?: string;
-
-  /**
-   * The updated status of the content. Note, if you change the status of a page from 'current' to 'draft' and it has an
-   * existing draft, the existing draft will be deleted in favor of the updated page.
-   */
-  statusBody?: 'current' | 'trashed' | 'historical' | 'draft';
-}
diff --git a/src/api/parameters/updateContentProperty.ts b/src/api/parameters/updateContentProperty.ts
deleted file mode 100644
index a9248224..00000000
--- a/src/api/parameters/updateContentProperty.ts
+++ /dev/null
@@ -1,8 +0,0 @@
-import type { ContentPropertyUpdate } from '../models';
-
-export interface UpdateContentProperty extends ContentPropertyUpdate {
-  /** The ID of the content that the property belongs to. */
-  id: string;
-  /** The key of the property. */
-  key: string;
-}
diff --git a/src/api/parameters/updateContentTemplate.ts b/src/api/parameters/updateContentTemplate.ts
deleted file mode 100644
index 71f92c63..00000000
--- a/src/api/parameters/updateContentTemplate.ts
+++ /dev/null
@@ -1,4 +0,0 @@
-import type { ContentTemplateUpdate } from '../models';
-
-/** This object is used to update content templates. */
-export interface UpdateContentTemplate extends ContentTemplateUpdate {}
diff --git a/src/api/parameters/updateLookAndFeel.ts b/src/api/parameters/updateLookAndFeel.ts
deleted file mode 100644
index 8116112c..00000000
--- a/src/api/parameters/updateLookAndFeel.ts
+++ /dev/null
@@ -1,3 +0,0 @@
-import type { LookAndFeelSelection } from '../models';
-
-export interface UpdateLookAndFeel extends LookAndFeelSelection {}
diff --git a/src/api/parameters/updateLookAndFeelSettings.ts b/src/api/parameters/updateLookAndFeelSettings.ts
deleted file mode 100644
index 0bef68af..00000000
--- a/src/api/parameters/updateLookAndFeelSettings.ts
+++ /dev/null
@@ -1,9 +0,0 @@
-import type { LookAndFeel } from '../models';
-
-export interface UpdateLookAndFeelSettings extends LookAndFeel {
-  /**
-   * The key of the space for which the look and feel settings will be updated. If this is not set, the global look and
-   * feel settings will be updated.
-   */
-  spaceKey?: string;
-}
diff --git a/src/api/parameters/updateRestrictions.ts b/src/api/parameters/updateRestrictions.ts
deleted file mode 100644
index 9e9c907e..00000000
--- a/src/api/parameters/updateRestrictions.ts
+++ /dev/null
@@ -1,15 +0,0 @@
-import type { ContentRestrictionUpdateArray } from '../models';
-
-export interface UpdateRestrictions {
-  /** The ID of the content to update restrictions for. */
-  id: string;
-  /**
-   * A multi-value parameter indicating which properties of the content restrictions (returned in response) to expand.
-   *
-   * - `restrictions.user` returns the piece of content that the restrictions are applied to. Expanded by default.
-   * - `restrictions.group` returns the piece of content that the restrictions are applied to. Expanded by default.
-   * - `content` returns the piece of content that the restrictions are applied to.
-   */
-  expand?: string[];
-  body: ContentRestrictionUpdateArray;
-}
diff --git a/src/api/parameters/updateSpace.ts b/src/api/parameters/updateSpace.ts
deleted file mode 100644
index 02926e8e..00000000
--- a/src/api/parameters/updateSpace.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-import type { SpaceUpdate } from '../models';
-
-export interface UpdateSpace extends SpaceUpdate {
-  /** The key of the space to update. */
-  spaceKey: string;
-}
diff --git a/src/api/parameters/updateSpaceProperty.ts b/src/api/parameters/updateSpaceProperty.ts
deleted file mode 100644
index 4c4e095f..00000000
--- a/src/api/parameters/updateSpaceProperty.ts
+++ /dev/null
@@ -1,8 +0,0 @@
-import type { SpacePropertyUpdate } from '../models';
-
-export interface UpdateSpaceProperty extends SpacePropertyUpdate {
-  /** The key of the space that the property is in. */
-  spaceKey: string;
-  /** The key of the property to be updated. */
-  key: string;
-}
diff --git a/src/api/parameters/updateSpaceSettings.ts b/src/api/parameters/updateSpaceSettings.ts
deleted file mode 100644
index c835d3f8..00000000
--- a/src/api/parameters/updateSpaceSettings.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-import type { SpaceSettingsUpdate } from '../models';
-
-export interface UpdateSpaceSettings extends SpaceSettingsUpdate {
-  /** The key of the space whose settings will be updated. */
-  spaceKey: string;
-}
diff --git a/src/api/parameters/updateTaskById.ts b/src/api/parameters/updateTaskById.ts
deleted file mode 100644
index 7de7f4fe..00000000
--- a/src/api/parameters/updateTaskById.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-import type { TaskStatusUpdate } from '../models';
-
-export interface UpdateTaskById extends TaskStatusUpdate {
-  /** Global ID of the inline task to update */
-  inlineTaskId: string;
-}
diff --git a/src/api/parameters/updateUserProperty.ts b/src/api/parameters/updateUserProperty.ts
deleted file mode 100644
index 7968204d..00000000
--- a/src/api/parameters/updateUserProperty.ts
+++ /dev/null
@@ -1,11 +0,0 @@
-import type { UserPropertyUpdate } from '../models';
-
-export interface UpdateUserProperty extends UserPropertyUpdate {
-  /**
-   * The account ID of the user. The accountId uniquely identifies the user across all Atlassian products. For example,
-   * 384093:32b4d9w0-f6a5-3535-11a3-9c8c88d10192
-   */
-  userId: string;
-  /** The key of the user property. */
-  key: string;
-}
diff --git a/src/api/relation.ts b/src/api/relation.ts
deleted file mode 100644
index 43c0b84e..00000000
--- a/src/api/relation.ts
+++ /dev/null
@@ -1,237 +0,0 @@
-import type * as Models from './models';
-import type * as Parameters from './parameters';
-import type { Client } from '../clients';
-import type { Callback } from '../callback';
-import type { RequestConfig } from '../requestConfig';
-
-export class Relation {
-  constructor(private client: Client) {}
-
-  /**
-   * Returns all target entities that have a particular relationship to the source entity. Note, relationships are one
-   * way.
-   *
-   * For example, the following method finds all content that the current user has an 'ignore' relationship with: `GET
-   * https://your-domain.atlassian.net/api/relation/ignore/from/user/current/to/content` Note, 'ignore' is an example
-   * custom relationship type.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to view both the target entity
-   * and source entity.
-   */
-  async findTargetFromSource(
-    parameters: Parameters.FindTargetFromSource,
-    callback: Callback,
-  ): Promise;
-  /**
-   * Returns all target entities that have a particular relationship to the source entity. Note, relationships are one
-   * way.
-   *
-   * For example, the following method finds all content that the current user has an 'ignore' relationship with: `GET
-   * https://your-domain.atlassian.net/api/relation/ignore/from/user/current/to/content` Note, 'ignore' is an example
-   * custom relationship type.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to view both the target entity
-   * and source entity.
-   */
-  async findTargetFromSource(
-    parameters: Parameters.FindTargetFromSource,
-    callback?: never,
-  ): Promise;
-  async findTargetFromSource(
-    parameters: Parameters.FindTargetFromSource,
-    callback?: Callback,
-  ): Promise {
-    const config: RequestConfig = {
-      url: `/api/relation/${parameters.relationName}/from/${parameters.sourceType}/${parameters.sourceKey}/to/${parameters.targetType}`,
-      method: 'GET',
-      params: {
-        sourceStatus: parameters.sourceStatus,
-        targetStatus: parameters.targetStatus,
-        sourceVersion: parameters.sourceVersion,
-        targetVersion: parameters.targetVersion,
-        expand: parameters.expand,
-        start: parameters.start,
-        limit: parameters.limit,
-      },
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-
-  /**
-   * Find whether a particular type of relationship exists from a source entity to a target entity. Note, relationships
-   * are one way.
-   *
-   * For example, you can use this method to find whether the current user has selected a particular page as a favorite
-   * (i.e. 'save for later'): `GET
-   * https://your-domain.atlassian.net/api/relation/favourite/from/user/current/to/content/123`
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to view both the target entity
-   * and source entity.
-   */
-  async getRelationship(
-    parameters: Parameters.GetRelationship,
-    callback: Callback,
-  ): Promise;
-  /**
-   * Find whether a particular type of relationship exists from a source entity to a target entity. Note, relationships
-   * are one way.
-   *
-   * For example, you can use this method to find whether the current user has selected a particular page as a favorite
-   * (i.e. 'save for later'): `GET
-   * https://your-domain.atlassian.net/api/relation/favourite/from/user/current/to/content/123`
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to view both the target entity
-   * and source entity.
-   */
-  async getRelationship(parameters: Parameters.GetRelationship, callback?: never): Promise;
-  async getRelationship(
-    parameters: Parameters.GetRelationship,
-    callback?: Callback,
-  ): Promise {
-    const config: RequestConfig = {
-      url: `/api/relation/${parameters.relationName}/from/${parameters.sourceType}/${parameters.sourceKey}/to/${parameters.targetType}/${parameters.targetKey}`,
-      method: 'GET',
-      params: {
-        sourceStatus: parameters.sourceStatus,
-        targetStatus: parameters.targetStatus,
-        sourceVersion: parameters.sourceVersion,
-        targetVersion: parameters.targetVersion,
-        expand: parameters.expand,
-      },
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-
-  /**
-   * Creates a relationship between two entities (user, space, content). The 'favourite' relationship is supported by
-   * default, but you can use this method to create any type of relationship between two entities.
-   *
-   * For example, the following method creates a 'sibling' relationship between two pieces of content: `GET
-   * https://your-domain.atlassian.net/api/relation/sibling/from/content/123/to/content/456`
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to access the Confluence site
-   * ('Can use' global permission).
-   */
-  async createRelationship(
-    parameters: Parameters.CreateRelationship,
-    callback: Callback,
-  ): Promise;
-  /**
-   * Creates a relationship between two entities (user, space, content). The 'favourite' relationship is supported by
-   * default, but you can use this method to create any type of relationship between two entities.
-   *
-   * For example, the following method creates a 'sibling' relationship between two pieces of content: `GET
-   * https://your-domain.atlassian.net/api/relation/sibling/from/content/123/to/content/456`
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to access the Confluence site
-   * ('Can use' global permission).
-   */
-  async createRelationship(
-    parameters: Parameters.CreateRelationship,
-    callback?: never,
-  ): Promise;
-  async createRelationship(
-    parameters: Parameters.CreateRelationship,
-    callback?: Callback,
-  ): Promise {
-    const config: RequestConfig = {
-      url: `/api/relation/${parameters.relationName}/from/${parameters.sourceType}/${parameters.sourceKey}/to/${parameters.targetType}/${parameters.targetKey}`,
-      method: 'PUT',
-      params: {
-        sourceStatus: parameters.sourceStatus,
-        targetStatus: parameters.targetStatus,
-        sourceVersion: parameters.sourceVersion,
-        targetVersion: parameters.targetVersion,
-      },
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-
-  /**
-   * Deletes a relationship between two entities (user, space, content).
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to access the Confluence site
-   * ('Can use' global permission). For favourite relationships, the current user can only delete their own favourite
-   * relationships. A space administrator can delete favourite relationships for any user.
-   */
-  async deleteRelationship(parameters: Parameters.DeleteRelationship, callback: Callback): Promise;
-  /**
-   * Deletes a relationship between two entities (user, space, content).
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to access the Confluence site
-   * ('Can use' global permission). For favourite relationships, the current user can only delete their own favourite
-   * relationships. A space administrator can delete favourite relationships for any user.
-   */
-  async deleteRelationship(parameters: Parameters.DeleteRelationship, callback?: never): Promise;
-  async deleteRelationship(
-    parameters: Parameters.DeleteRelationship,
-    callback?: Callback,
-  ): Promise {
-    const config: RequestConfig = {
-      url: `/api/relation/${parameters.relationName}/from/${parameters.sourceType}/${parameters.sourceKey}/to/${parameters.targetType}/${parameters.targetKey}`,
-      method: 'DELETE',
-      params: {
-        sourceStatus: parameters.sourceStatus,
-        targetStatus: parameters.targetStatus,
-        sourceVersion: parameters.sourceVersion,
-        targetVersion: parameters.targetVersion,
-      },
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-
-  /**
-   * Returns all target entities that have a particular relationship to the source entity. Note, relationships are one
-   * way.
-   *
-   * For example, the following method finds all users that have a 'collaborator' relationship to a piece of content
-   * with an ID of '1234': `GET https://your-domain.atlassian.net/api/relation/collaborator/to/content/1234/from/user`
-   * Note, 'collaborator' is an example custom relationship type.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to view both the target entity
-   * and source entity.
-   */
-  async findSourcesForTarget(
-    parameters: Parameters.FindSourcesForTarget,
-    callback: Callback,
-  ): Promise;
-  /**
-   * Returns all target entities that have a particular relationship to the source entity. Note, relationships are one
-   * way.
-   *
-   * For example, the following method finds all users that have a 'collaborator' relationship to a piece of content
-   * with an ID of '1234': `GET https://your-domain.atlassian.net/api/relation/collaborator/to/content/1234/from/user`
-   * Note, 'collaborator' is an example custom relationship type.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to view both the target entity
-   * and source entity.
-   */
-  async findSourcesForTarget(
-    parameters: Parameters.FindSourcesForTarget,
-    callback?: never,
-  ): Promise;
-  async findSourcesForTarget(
-    parameters: Parameters.FindSourcesForTarget,
-    callback?: Callback,
-  ): Promise {
-    const config: RequestConfig = {
-      url: `/api/relation/${parameters.relationName}/to/${parameters.targetType}/${parameters.targetKey}/from/${parameters.sourceType}`,
-      method: 'GET',
-      params: {
-        sourceStatus: parameters.sourceStatus,
-        targetStatus: parameters.targetStatus,
-        sourceVersion: parameters.sourceVersion,
-        targetVersion: parameters.targetVersion,
-        expand: parameters.expand,
-        start: parameters.start,
-        limit: parameters.limit,
-      },
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-}
diff --git a/src/api/search.ts b/src/api/search.ts
deleted file mode 100644
index b4df14fc..00000000
--- a/src/api/search.ts
+++ /dev/null
@@ -1,112 +0,0 @@
-import type * as Models from './models';
-import type * as Parameters from './parameters';
-import type { Client } from '../clients';
-import type { Callback } from '../callback';
-import type { RequestConfig } from '../requestConfig';
-
-export class Search {
-  constructor(private client: Client) {}
-
-  /**
-   * Searches for content using the [Confluence Query Language
-   * (CQL)](https://developer.atlassian.com/cloud/confluence/advanced-searching-using-cql/)
-   *
-   * When additional results are available, returns `next` and `prev` URLs to retrieve them in subsequent calls. The
-   * URLs each contain a cursor that points to the appropriate set of results. Use `limit` to specify the number of
-   * results returned in each call.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to view the entities. Note, only
-   * entities that the user has permission to view will be returned.
-   */
-  async searchByCQL(
-    parameters: Parameters.SearchByCQL,
-    callback: Callback,
-  ): Promise;
-  /**
-   * Searches for content using the [Confluence Query Language
-   * (CQL)](https://developer.atlassian.com/cloud/confluence/advanced-searching-using-cql/)
-   *
-   * When additional results are available, returns `next` and `prev` URLs to retrieve them in subsequent calls. The
-   * URLs each contain a cursor that points to the appropriate set of results. Use `limit` to specify the number of
-   * results returned in each call.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to view the entities. Note, only
-   * entities that the user has permission to view will be returned.
-   */
-  async searchByCQL(
-    parameters: Parameters.SearchByCQL,
-    callback?: never,
-  ): Promise;
-  async searchByCQL(
-    parameters: Parameters.SearchByCQL,
-    callback?: Callback,
-  ): Promise {
-    const config: RequestConfig = {
-      url: '/api/search',
-      method: 'GET',
-      params: {
-        cql: parameters.cql,
-        cqlcontext: parameters.cqlcontext,
-        cursor: parameters.cursor,
-        next: parameters.next,
-        prev: parameters.prev,
-        limit: parameters.limit,
-        start: parameters.start,
-        includeArchivedSpaces: parameters.includeArchivedSpaces,
-        excludeCurrentSpaces: parameters.excludeCurrentSpaces,
-        excerpt: parameters.excerpt,
-        sitePermissionTypeFilter: parameters.sitePermissionTypeFilter,
-        expand: parameters.expand,
-      },
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-
-  /**
-   * Searches for users using user-specific queries from the [Confluence Query Language
-   * (CQL)](https://developer.atlassian.com/cloud/confluence/advanced-searching-using-cql/).
-   *
-   * Note that CQL input queries submitted through the `/api/search/user` endpoint only support user-specific fields
-   * like `user`, `user.fullname`, `user.accountid`, and `user.userkey`.
-   *
-   * Note that some user fields may be set to null depending on the user's privacy settings. These are: email,
-   * profilePicture, displayName, and timeZone.
-   */
-  async searchUser(
-    parameters: Parameters.SearchUser,
-    callback: Callback,
-  ): Promise;
-  /**
-   * Searches for users using user-specific queries from the [Confluence Query Language
-   * (CQL)](https://developer.atlassian.com/cloud/confluence/advanced-searching-using-cql/).
-   *
-   * Note that CQL input queries submitted through the `/api/search/user` endpoint only support user-specific fields
-   * like `user`, `user.fullname`, `user.accountid`, and `user.userkey`.
-   *
-   * Note that some user fields may be set to null depending on the user's privacy settings. These are: email,
-   * profilePicture, displayName, and timeZone.
-   */
-  async searchUser(
-    parameters: Parameters.SearchUser,
-    callback?: never,
-  ): Promise;
-  async searchUser(
-    parameters: Parameters.SearchUser,
-    callback?: Callback,
-  ): Promise {
-    const config: RequestConfig = {
-      url: '/api/search/user',
-      method: 'GET',
-      params: {
-        cql: parameters.cql,
-        start: parameters.start,
-        limit: parameters.limit,
-        expand: parameters.expand,
-        sitePermissionTypeFilter: parameters.sitePermissionTypeFilter,
-      },
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-}
diff --git a/src/api/settings.ts b/src/api/settings.ts
deleted file mode 100644
index d7cdae05..00000000
--- a/src/api/settings.ts
+++ /dev/null
@@ -1,239 +0,0 @@
-import type * as Models from './models';
-import type * as Parameters from './parameters';
-import type { Client } from '../clients';
-import type { Callback } from '../callback';
-import type { RequestConfig } from '../requestConfig';
-
-export class Settings {
-  constructor(private client: Client) {}
-
-  /**
-   * Returns the look and feel settings for the site or a single space. This includes attributes such as the color
-   * scheme, padding, and border radius.
-   *
-   * The look and feel settings for a space can be inherited from the global look and feel settings or provided by a
-   * theme.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: None
-   */
-  async getLookAndFeelSettings(
-    parameters: Parameters.GetLookAndFeelSettings | undefined,
-    callback: Callback,
-  ): Promise;
-  /**
-   * Returns the look and feel settings for the site or a single space. This includes attributes such as the color
-   * scheme, padding, and border radius.
-   *
-   * The look and feel settings for a space can be inherited from the global look and feel settings or provided by a
-   * theme.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: None
-   */
-  async getLookAndFeelSettings(
-    parameters?: Parameters.GetLookAndFeelSettings,
-    callback?: never,
-  ): Promise;
-  async getLookAndFeelSettings(
-    parameters?: Parameters.GetLookAndFeelSettings,
-    callback?: Callback,
-  ): Promise {
-    const config: RequestConfig = {
-      url: '/api/settings/lookandfeel',
-      method: 'GET',
-      params: {
-        spaceKey: parameters?.spaceKey,
-      },
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-
-  /**
-   * Sets the look and feel settings to the default (global) settings, the custom settings, or the current theme's
-   * settings for a space. The custom and theme settings can only be selected if there is already a theme set for a
-   * space. Note, the default space settings are inherited from the current global settings.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'Admin' permission for the space.
-   */
-  async updateLookAndFeel(
-    parameters: Parameters.UpdateLookAndFeel | undefined,
-    callback: Callback,
-  ): Promise;
-  /**
-   * Sets the look and feel settings to the default (global) settings, the custom settings, or the current theme's
-   * settings for a space. The custom and theme settings can only be selected if there is already a theme set for a
-   * space. Note, the default space settings are inherited from the current global settings.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'Admin' permission for the space.
-   */
-  async updateLookAndFeel(
-    parameters?: Parameters.UpdateLookAndFeel,
-    callback?: never,
-  ): Promise;
-  async updateLookAndFeel(
-    parameters?: Parameters.UpdateLookAndFeel,
-    callback?: Callback,
-  ): Promise {
-    const config: RequestConfig = {
-      url: '/api/settings/lookandfeel',
-      method: 'PUT',
-      data: {
-        spaceKey: parameters?.spaceKey,
-        lookAndFeelType: parameters?.lookAndFeelType,
-      },
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-
-  /**
-   * Updates the look and feel settings for the site or for a single space. If custom settings exist, they are updated.
-   * If no custom settings exist, then a set of custom settings is created.
-   *
-   * Note, if a theme is selected for a space, the space look and feel settings are provided by the theme and cannot be
-   * overridden.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'Admin' permission for the space.
-   */
-  async updateLookAndFeelSettings(
-    parameters: Parameters.UpdateLookAndFeelSettings | undefined,
-    callback: Callback,
-  ): Promise;
-  /**
-   * Updates the look and feel settings for the site or for a single space. If custom settings exist, they are updated.
-   * If no custom settings exist, then a set of custom settings is created.
-   *
-   * Note, if a theme is selected for a space, the space look and feel settings are provided by the theme and cannot be
-   * overridden.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'Admin' permission for the space.
-   */
-  async updateLookAndFeelSettings(
-    parameters?: Parameters.UpdateLookAndFeelSettings,
-    callback?: never,
-  ): Promise;
-  async updateLookAndFeelSettings(
-    parameters?: Parameters.UpdateLookAndFeelSettings,
-    callback?: Callback,
-  ): Promise {
-    const config: RequestConfig = {
-      url: '/api/settings/lookandfeel/custom',
-      method: 'POST',
-      params: {
-        spaceKey: parameters?.spaceKey,
-      },
-      data: {
-        headings: parameters?.headings,
-        links: parameters?.links,
-        menus: parameters?.menus,
-        header: parameters?.header,
-        horizontalHeader: parameters?.horizontalHeader,
-        content: parameters?.content,
-        bordersAndDividers: parameters?.bordersAndDividers,
-        spaceReference: parameters?.spaceReference,
-        _links: parameters?.links,
-      },
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-
-  /**
-   * Resets the custom look and feel settings for the site or a single space. This changes the values of the custom
-   * settings to be the same as the default settings. It does not change which settings (default or custom) are
-   * selected. Note, the default space settings are inherited from the current global settings.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'Admin' permission for the space.
-   */
-  async resetLookAndFeelSettings(
-    parameters: Parameters.ResetLookAndFeelSettings | undefined,
-    callback: Callback,
-  ): Promise;
-  /**
-   * Resets the custom look and feel settings for the site or a single space. This changes the values of the custom
-   * settings to be the same as the default settings. It does not change which settings (default or custom) are
-   * selected. Note, the default space settings are inherited from the current global settings.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'Admin' permission for the space.
-   */
-  async resetLookAndFeelSettings(
-    parameters?: Parameters.ResetLookAndFeelSettings,
-    callback?: never,
-  ): Promise;
-  async resetLookAndFeelSettings(
-    parameters?: Parameters.ResetLookAndFeelSettings,
-    callback?: Callback,
-  ): Promise {
-    const config: RequestConfig = {
-      url: '/api/settings/lookandfeel/custom',
-      method: 'DELETE',
-      params: {
-        spaceKey: parameters?.spaceKey,
-      },
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-
-  /**
-   * Sets the look and feel settings to either the default settings or the custom settings, for the site or a single
-   * space. Note, the default space settings are inherited from the current global settings.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'Admin' permission for the space.
-   *
-   * @deprecated Will be removed in next major version.
-   */
-  async setLookAndFeelSettings(
-    parameters: Parameters.SetLookAndFeelSettings | undefined,
-    callback: Callback,
-  ): Promise;
-  /**
-   * Sets the look and feel settings to either the default settings or the custom settings, for the site or a single
-   * space. Note, the default space settings are inherited from the current global settings.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'Admin' permission for the space.
-   *
-   * @deprecated Will be removed in next major version.
-   */
-  async setLookAndFeelSettings(
-    parameters?: Parameters.SetLookAndFeelSettings,
-    callback?: never,
-  ): Promise;
-  async setLookAndFeelSettings(
-    parameters?: Parameters.SetLookAndFeelSettings,
-    callback?: Callback,
-  ): Promise {
-    const config: RequestConfig = {
-      url: '/api/settings/lookandfeel/selected',
-      method: 'PUT',
-      params: {
-        spaceKey: parameters?.spaceKey,
-      },
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-
-  /**
-   * Returns the system information for the Confluence Cloud tenant. This information is used by Atlassian.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to access the Confluence site
-   * ('Can use' global permission).
-   */
-  async getSystemInfo(callback: Callback): Promise;
-  /**
-   * Returns the system information for the Confluence Cloud tenant. This information is used by Atlassian.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to access the Confluence site
-   * ('Can use' global permission).
-   */
-  async getSystemInfo(callback?: never): Promise;
-  async getSystemInfo(callback?: Callback): Promise {
-    const config: RequestConfig = {
-      url: '/api/settings/systemInfo',
-      method: 'GET',
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-}
diff --git a/src/api/space.ts b/src/api/space.ts
deleted file mode 100644
index ecfeb88e..00000000
--- a/src/api/space.ts
+++ /dev/null
@@ -1,301 +0,0 @@
-import type * as Models from './models';
-import type * as Parameters from './parameters';
-import type { Client } from '../clients';
-import type { Callback } from '../callback';
-import { paramSerializer } from '../paramSerializer';
-import type { RequestConfig } from '../requestConfig';
-
-export class Space {
-  constructor(private client: Client) {}
-
-  /**
-   * Returns all spaces. The returned spaces are ordered alphabetically in ascending order by space key.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to access the Confluence site
-   * ('Can use' global permission). Note, the returned list will only contain spaces that the current user has
-   * permission to view.
-   *
-   * @deprecated Will be removed in next major version.
-   */
-  async getSpaces(
-    parameters: Parameters.GetSpaces | undefined,
-    callback: Callback,
-  ): Promise;
-  /**
-   * Returns all spaces. The returned spaces are ordered alphabetically in ascending order by space key.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to access the Confluence site
-   * ('Can use' global permission). Note, the returned list will only contain spaces that the current user has
-   * permission to view.
-   *
-   * @deprecated Will be removed in next major version.
-   */
-  async getSpaces(parameters?: Parameters.GetSpaces, callback?: never): Promise;
-  async getSpaces(parameters?: Parameters.GetSpaces, callback?: Callback): Promise {
-    const config: RequestConfig = {
-      url: '/api/space',
-      method: 'GET',
-      params: {
-        spaceKey: paramSerializer('spaceKey', parameters?.spaceKey),
-        spaceId: parameters?.spaceId,
-        type: parameters?.type,
-        status: parameters?.status,
-        label: parameters?.label,
-        favourite: parameters?.favourite,
-        favouriteUserKey: parameters?.favouriteUserKey,
-        start: parameters?.start,
-        limit: parameters?.limit,
-        expand: parameters?.expand,
-      },
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-
-  /**
-   * Creates a new space. Note, currently you cannot set space labels when creating a space.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'Create Space(s)' global permission.
-   */
-  async createSpace(
-    parameters: Parameters.CreateSpace | undefined,
-    callback: Callback,
-  ): Promise;
-  /**
-   * Creates a new space. Note, currently you cannot set space labels when creating a space.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'Create Space(s)' global permission.
-   */
-  async createSpace(parameters?: Parameters.CreateSpace, callback?: never): Promise;
-  async createSpace(parameters?: Parameters.CreateSpace, callback?: Callback): Promise {
-    const config: RequestConfig = {
-      url: '/api/space',
-      method: 'POST',
-      data: {
-        name: parameters?.name,
-        key: parameters?.key,
-        alias: parameters?.alias,
-        description: parameters?.description,
-        permissions: parameters?.permissions,
-      },
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-
-  /**
-   * Creates a new space that is only visible to the creator. This method is the same as the [Create
-   * space](#api-space-post) method with permissions set to the current user only. Note, currently you cannot set space
-   * labels when creating a space.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'Create Space(s)' global permission.
-   */
-  async createPrivateSpace(
-    parameters: Parameters.CreatePrivateSpace | undefined,
-    callback: Callback,
-  ): Promise;
-  /**
-   * Creates a new space that is only visible to the creator. This method is the same as the [Create
-   * space](#api-space-post) method with permissions set to the current user only. Note, currently you cannot set space
-   * labels when creating a space.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'Create Space(s)' global permission.
-   */
-  async createPrivateSpace(parameters?: Parameters.CreatePrivateSpace, callback?: never): Promise;
-  async createPrivateSpace(
-    parameters?: Parameters.CreatePrivateSpace,
-    callback?: Callback,
-  ): Promise {
-    const config: RequestConfig = {
-      url: '/api/space/_private',
-      method: 'POST',
-      data: {
-        name: parameters?.name,
-        key: parameters?.key,
-        alias: parameters?.alias,
-        description: parameters?.description,
-        permissions: parameters?.permissions,
-      },
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-
-  /**
-   * Returns a space. This includes information like the name, description, and permissions, but not the content in the
-   * space.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'View' permission for the space.
-   *
-   * @deprecated Will be removed in next major version.
-   */
-  async getSpace(parameters: Parameters.GetSpace, callback: Callback): Promise;
-  /**
-   * Returns a space. This includes information like the name, description, and permissions, but not the content in the
-   * space.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'View' permission for the space.
-   *
-   * @deprecated Will be removed in next major version.
-   */
-  async getSpace(parameters: Parameters.GetSpace, callback?: never): Promise;
-  async getSpace(parameters: Parameters.GetSpace, callback?: Callback): Promise {
-    const config: RequestConfig = {
-      url: `/api/space/${parameters.spaceKey}`,
-      method: 'GET',
-      params: {
-        expand: parameters.expand,
-      },
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-
-  /**
-   * Updates the name, description, or homepage of a space.
-   *
-   * - For security reasons, permissions cannot be updated via the API and must be changed via the user interface instead.
-   * - Currently you cannot set space labels when updating a space.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'Admin' permission for the space.
-   */
-  async updateSpace(parameters: Parameters.UpdateSpace, callback: Callback): Promise;
-  /**
-   * Updates the name, description, or homepage of a space.
-   *
-   * - For security reasons, permissions cannot be updated via the API and must be changed via the user interface instead.
-   * - Currently you cannot set space labels when updating a space.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'Admin' permission for the space.
-   */
-  async updateSpace(parameters: Parameters.UpdateSpace, callback?: never): Promise;
-  async updateSpace(parameters: Parameters.UpdateSpace, callback?: Callback): Promise {
-    const config: RequestConfig = {
-      url: `/api/space/${parameters.spaceKey}`,
-      method: 'PUT',
-      data: {
-        name: parameters.name,
-        description: parameters.description,
-        homepage: parameters.homepage,
-        type: parameters.type,
-        status: parameters.status,
-      },
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-
-  /**
-   * Permanently deletes a space without sending it to the trash. Note, the space will be deleted in a long running
-   * task. Therefore, the space may not be deleted yet when this method has returned. Clients should poll the status
-   * link that is returned in the response until the task completes.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'Admin' permission for the space.
-   */
-  async deleteSpace(parameters: Parameters.DeleteSpace, callback: Callback): Promise;
-  /**
-   * Permanently deletes a space without sending it to the trash. Note, the space will be deleted in a long running
-   * task. Therefore, the space may not be deleted yet when this method has returned. Clients should poll the status
-   * link that is returned in the response until the task completes.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'Admin' permission for the space.
-   */
-  async deleteSpace(parameters: Parameters.DeleteSpace, callback?: never): Promise;
-  async deleteSpace(
-    parameters: Parameters.DeleteSpace,
-    callback?: Callback,
-  ): Promise {
-    const config: RequestConfig = {
-      url: `/api/space/${parameters.spaceKey}`,
-      method: 'DELETE',
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-
-  /**
-   * Returns all content in a space. The returned content is grouped by type (pages then blogposts), then ordered by
-   * content ID in ascending order.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'View' permission for the space. Note, the
-   * returned list will only contain content that the current user has permission to view.
-   *
-   * @deprecated Will be removed in next major version.
-   */
-  async getContentForSpace(
-    parameters: Parameters.GetContentForSpace,
-    callback: Callback,
-  ): Promise;
-  /**
-   * Returns all content in a space. The returned content is grouped by type (pages then blogposts), then ordered by
-   * content ID in ascending order.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'View' permission for the space. Note, the
-   * returned list will only contain content that the current user has permission to view.
-   *
-   * @deprecated Will be removed in next major version.
-   */
-  async getContentForSpace(
-    parameters: Parameters.GetContentForSpace,
-    callback?: never,
-  ): Promise;
-  async getContentForSpace(
-    parameters: Parameters.GetContentForSpace,
-    callback?: Callback,
-  ): Promise {
-    const config: RequestConfig = {
-      url: `/api/space/${parameters.spaceKey}/content`,
-      method: 'GET',
-      params: {
-        depth: parameters.depth,
-        expand: parameters.expand,
-        start: parameters.start,
-        limit: parameters.limit,
-      },
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-
-  /**
-   * Returns all content of a given type, in a space. The returned content is ordered by content ID in ascending order.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'View' permission for the space. Note, the
-   * returned list will only contain content that the current user has permission to view.
-   *
-   * @deprecated Will be removed in next major version.
-   */
-  async getContentByTypeForSpace(
-    parameters: Parameters.GetContentByTypeForSpace,
-    callback: Callback,
-  ): Promise;
-  /**
-   * Returns all content of a given type, in a space. The returned content is ordered by content ID in ascending order.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'View' permission for the space. Note, the
-   * returned list will only contain content that the current user has permission to view.
-   *
-   * @deprecated Will be removed in next major version.
-   */
-  async getContentByTypeForSpace(
-    parameters: Parameters.GetContentByTypeForSpace,
-    callback?: never,
-  ): Promise;
-  async getContentByTypeForSpace(
-    parameters: Parameters.GetContentByTypeForSpace,
-    callback?: Callback,
-  ): Promise {
-    const config: RequestConfig = {
-      url: `/api/space/${parameters.spaceKey}/content/${parameters.type}`,
-      method: 'GET',
-      params: {
-        depth: parameters.depth,
-        expand: parameters.expand,
-        start: parameters.start,
-        limit: parameters.limit,
-      },
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-}
diff --git a/src/api/spacePermissions.ts b/src/api/spacePermissions.ts
deleted file mode 100644
index f1b14c4f..00000000
--- a/src/api/spacePermissions.ts
+++ /dev/null
@@ -1,121 +0,0 @@
-import type * as Models from './models';
-import type * as Parameters from './parameters';
-import type { Client } from '../clients';
-import type { Callback } from '../callback';
-import type { RequestConfig } from '../requestConfig';
-
-export class SpacePermissions {
-  constructor(private client: Client) {}
-
-  /**
-   * Adds new permission to space.
-   *
-   * If the permission to be added is a group permission, the group can be identified by its group name or group id.
-   *
-   * Note: Apps cannot access this REST resource - including when utilizing user impersonation.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'Admin' permission for the space.
-   */
-  async addPermissionToSpace(
-    parameters: Parameters.AddPermissionToSpace,
-    callback: Callback,
-  ): Promise;
-  /**
-   * Adds new permission to space.
-   *
-   * If the permission to be added is a group permission, the group can be identified by its group name or group id.
-   *
-   * Note: Apps cannot access this REST resource - including when utilizing user impersonation.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'Admin' permission for the space.
-   */
-  async addPermissionToSpace(
-    parameters: Parameters.AddPermissionToSpace,
-    callback?: never,
-  ): Promise;
-  async addPermissionToSpace(
-    parameters: Parameters.AddPermissionToSpace,
-    callback?: Callback,
-  ): Promise {
-    const config: RequestConfig = {
-      url: `/api/space/${parameters.spaceKey}/permission`,
-      method: 'POST',
-      data: {
-        subject: parameters.subject,
-        operation: parameters.operation,
-        _links: parameters.links,
-      },
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-
-  /**
-   * Adds new custom content permission to space.
-   *
-   * If the permission to be added is a group permission, the group can be identified by its group name or group id.
-   *
-   * Note: Only apps can access this REST resource and only make changes to the respective app permissions.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'Admin' permission for the space.
-   */
-  async addCustomContentPermissions(
-    parameters: Parameters.AddCustomContentPermissions,
-    callback: Callback,
-  ): Promise;
-  /**
-   * Adds new custom content permission to space.
-   *
-   * If the permission to be added is a group permission, the group can be identified by its group name or group id.
-   *
-   * Note: Only apps can access this REST resource and only make changes to the respective app permissions.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'Admin' permission for the space.
-   */
-  async addCustomContentPermissions(
-    parameters: Parameters.AddCustomContentPermissions,
-    callback?: never,
-  ): Promise;
-  async addCustomContentPermissions(
-    parameters: Parameters.AddCustomContentPermissions,
-    callback?: Callback,
-  ): Promise {
-    const config: RequestConfig = {
-      url: `/api/space/${parameters.spaceKey}/permission/custom-content`,
-      method: 'POST',
-      data: {
-        subject: parameters.subject,
-        operations: parameters.operations,
-      },
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-
-  /**
-   * Removes a space permission. Note that removing Read Space permission for a user or group will remove all the space
-   * permissions for that user or group.
-   *
-   * Note: Apps cannot access this REST resource - including when utilizing user impersonation.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'Admin' permission for the space.
-   */
-  async removePermission(parameters: Parameters.RemovePermission, callback: Callback): Promise;
-  /**
-   * Removes a space permission. Note that removing Read Space permission for a user or group will remove all the space
-   * permissions for that user or group.
-   *
-   * Note: Apps cannot access this REST resource - including when utilizing user impersonation.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'Admin' permission for the space.
-   */
-  async removePermission(parameters: Parameters.RemovePermission, callback?: never): Promise;
-  async removePermission(parameters: Parameters.RemovePermission, callback?: Callback): Promise {
-    const config: RequestConfig = {
-      url: `/api/space/${parameters.spaceKey}/permission/${parameters.id}`,
-      method: 'DELETE',
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-}
diff --git a/src/api/spaceProperties.ts b/src/api/spaceProperties.ts
deleted file mode 100644
index b7fe0731..00000000
--- a/src/api/spaceProperties.ts
+++ /dev/null
@@ -1,230 +0,0 @@
-import type * as Models from './models';
-import type * as Parameters from './parameters';
-import type { Callback } from '../callback';
-import type { Client } from '../clients';
-import type { RequestConfig } from '../requestConfig';
-
-/** @deprecated Will be removed in next major version. */
-export class SpaceProperties {
-  constructor(private client: Client) {}
-
-  /**
-   * Returns all properties for the given space. Space properties are a key-value storage associated with a space.
-   *
-   * **[Permissions required](https://confluence.atlassian.com/x/_AozKw)**: ‘View’ permission for the space.
-   *
-   * @deprecated Will be removed in next major version.
-   */
-  async getSpaceProperties(
-    parameters: Parameters.GetSpaceProperties,
-    callback: Callback,
-  ): Promise;
-  /**
-   * Returns all properties for the given space. Space properties are a key-value storage associated with a space.
-   *
-   * **[Permissions required](https://confluence.atlassian.com/x/_AozKw)**: ‘View’ permission for the space.
-   *
-   * @deprecated Will be removed in next major version.
-   */
-  async getSpaceProperties(
-    parameters: Parameters.GetSpaceProperties,
-    callback?: never,
-  ): Promise;
-  async getSpaceProperties(
-    parameters: Parameters.GetSpaceProperties,
-    callback?: Callback,
-  ): Promise {
-    const config: RequestConfig = {
-      url: `/api/space/${parameters.spaceKey}/property`,
-      method: 'GET',
-      params: {
-        expand: parameters.expand,
-        start: parameters.start,
-        limit: parameters.limit,
-      },
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-
-  /**
-   * Creates a new space property.
-   *
-   * **[Permissions required](https://confluence.atlassian.com/x/_AozKw)**: ‘Admin’ permission for the space.
-   *
-   * @deprecated Will be removed in next major version.
-   */
-  async createSpaceProperty(
-    parameters: Parameters.CreateSpaceProperty,
-    callback: Callback,
-  ): Promise;
-  /**
-   * Creates a new space property.
-   *
-   * **[Permissions required](https://confluence.atlassian.com/x/_AozKw)**: ‘Admin’ permission for the space.
-   *
-   * @deprecated Will be removed in next major version.
-   */
-  async createSpaceProperty(
-    parameters: Parameters.CreateSpaceProperty,
-    callback?: never,
-  ): Promise;
-  async createSpaceProperty(
-    parameters: Parameters.CreateSpaceProperty,
-    callback?: Callback,
-  ): Promise {
-    const config: RequestConfig = {
-      url: `/api/space/${parameters.spaceKey}/property`,
-      method: 'POST',
-      data: {
-        key: parameters.key,
-        value: parameters.value,
-        space: parameters.space,
-      },
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-
-  /**
-   * Returns a space property.
-   *
-   * **[Permissions required](https://confluence.atlassian.com/x/_AozKw)**: ‘View’ permission for the space.
-   *
-   * @deprecated Will be removed in next major version.
-   */
-  async getSpaceProperty(
-    parameters: Parameters.GetSpaceProperty,
-    callback: Callback,
-  ): Promise;
-  /**
-   * Returns a space property.
-   *
-   * **[Permissions required](https://confluence.atlassian.com/x/_AozKw)**: ‘View’ permission for the space.
-   *
-   * @deprecated Will be removed in next major version.
-   */
-  async getSpaceProperty(
-    parameters: Parameters.GetSpaceProperty,
-    callback?: never,
-  ): Promise;
-  async getSpaceProperty(
-    parameters: Parameters.GetSpaceProperty,
-    callback?: Callback,
-  ): Promise {
-    const config: RequestConfig = {
-      url: `/api/space/${parameters.spaceKey}/property/${parameters.key}`,
-      method: 'GET',
-      params: {
-        expand: parameters.expand,
-      },
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-
-  /**
-   * Creates a new space property. This is the same as `POST /api/space/{spaceKey}/property` but the key for the
-   * property is passed as a path parameter, rather than in the request body.
-   *
-   * **[Permissions required](https://confluence.atlassian.com/x/_AozKw)**: ‘Admin’ permission for the space.
-   *
-   * @deprecated Will be removed in next major version.
-   */
-  async createSpacePropertyForKey(
-    parameters: Parameters.CreateSpacePropertyForKey,
-    callback: Callback,
-  ): Promise;
-  /**
-   * Creates a new space property. This is the same as `POST /api/space/{spaceKey}/property` but the key for the
-   * property is passed as a path parameter, rather than in the request body.
-   *
-   * **[Permissions required](https://confluence.atlassian.com/x/_AozKw)**: ‘Admin’ permission for the space.
-   *
-   * @deprecated Will be removed in next major version.
-   */
-  async createSpacePropertyForKey(
-    parameters: Parameters.CreateSpacePropertyForKey,
-    callback?: never,
-  ): Promise;
-  async createSpacePropertyForKey(
-    parameters: Parameters.CreateSpacePropertyForKey,
-    callback?: Callback,
-  ): Promise {
-    const config: RequestConfig = {
-      url: `/api/space/${parameters.spaceKey}/property/${parameters.key}`,
-      method: 'POST',
-      data: {
-        value: parameters.value,
-      },
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-
-  /**
-   * Updates a space property. Note, you cannot update the key of a space property, only the value.
-   *
-   * **[Permissions required](https://confluence.atlassian.com/x/_AozKw)**: ‘Admin’ permission for the space.
-   *
-   * @deprecated Will be removed in next major version.
-   */
-  async updateSpaceProperty(
-    parameters: Parameters.UpdateSpaceProperty,
-    callback: Callback,
-  ): Promise;
-  /**
-   * Updates a space property. Note, you cannot update the key of a space property, only the value.
-   *
-   * **[Permissions required](https://confluence.atlassian.com/x/_AozKw)**: ‘Admin’ permission for the space.
-   *
-   * @deprecated Will be removed in next major version.
-   */
-  async updateSpaceProperty(
-    parameters: Parameters.UpdateSpaceProperty,
-    callback?: never,
-  ): Promise;
-  async updateSpaceProperty(
-    parameters: Parameters.UpdateSpaceProperty,
-    callback?: Callback,
-  ): Promise {
-    const config: RequestConfig = {
-      url: `/api/space/${parameters.spaceKey}/property/${parameters.key}`,
-      method: 'PUT',
-      data: {
-        value: parameters.value,
-        version: parameters.version,
-      },
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-
-  /**
-   * Deletes a space property.
-   *
-   * **[Permissions required](https://confluence.atlassian.com/x/_AozKw)**: ‘Admin’ permission for the space.
-   *
-   * @deprecated Will be removed in next major version.
-   */
-  async deleteSpaceProperty(parameters: Parameters.DeleteSpaceProperty, callback: Callback): Promise;
-  /**
-   * Deletes a space property.
-   *
-   * **[Permissions required](https://confluence.atlassian.com/x/_AozKw)**: ‘Admin’ permission for the space.
-   *
-   * @deprecated Will be removed in next major version.
-   */
-  async deleteSpaceProperty(parameters: Parameters.DeleteSpaceProperty, callback?: never): Promise;
-  async deleteSpaceProperty(
-    parameters: Parameters.DeleteSpaceProperty,
-    callback?: Callback,
-  ): Promise {
-    const config: RequestConfig = {
-      url: `/api/space/${parameters.spaceKey}/property/${parameters.key}`,
-      method: 'DELETE',
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-}
diff --git a/src/api/spaceSettings.ts b/src/api/spaceSettings.ts
deleted file mode 100644
index aab1685b..00000000
--- a/src/api/spaceSettings.ts
+++ /dev/null
@@ -1,72 +0,0 @@
-import type * as Models from './models';
-import type * as Parameters from './parameters';
-import type { Client } from '../clients';
-import type { Callback } from '../callback';
-import type { RequestConfig } from '../requestConfig';
-
-export class SpaceSettings {
-  constructor(private client: Client) {}
-
-  /**
-   * Returns the settings of a space. Currently only the `routeOverrideEnabled` setting can be returned.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'View' permission for the space.
-   */
-  async getSpaceSettings(
-    parameters: Parameters.GetSpaceSettings,
-    callback: Callback,
-  ): Promise;
-  /**
-   * Returns the settings of a space. Currently only the `routeOverrideEnabled` setting can be returned.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'View' permission for the space.
-   */
-  async getSpaceSettings(
-    parameters: Parameters.GetSpaceSettings,
-    callback?: never,
-  ): Promise;
-  async getSpaceSettings(
-    parameters: Parameters.GetSpaceSettings,
-    callback?: Callback,
-  ): Promise {
-    const config: RequestConfig = {
-      url: `/api/space/${parameters.spaceKey}/settings`,
-      method: 'GET',
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-
-  /**
-   * Updates the settings for a space. Currently only the `routeOverrideEnabled` setting can be updated.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'Admin' permission for the space.
-   */
-  async updateSpaceSettings(
-    parameters: Parameters.UpdateSpaceSettings,
-    callback: Callback,
-  ): Promise;
-  /**
-   * Updates the settings for a space. Currently only the `routeOverrideEnabled` setting can be updated.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'Admin' permission for the space.
-   */
-  async updateSpaceSettings(
-    parameters: Parameters.UpdateSpaceSettings,
-    callback?: never,
-  ): Promise;
-  async updateSpaceSettings(
-    parameters: Parameters.UpdateSpaceSettings,
-    callback?: Callback,
-  ): Promise {
-    const config: RequestConfig = {
-      url: `/api/space/${parameters.spaceKey}/settings`,
-      method: 'PUT',
-      data: {
-        routeOverrideEnabled: parameters.routeOverrideEnabled,
-      },
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-}
diff --git a/src/api/template.ts b/src/api/template.ts
deleted file mode 100644
index 52975269..00000000
--- a/src/api/template.ts
+++ /dev/null
@@ -1,255 +0,0 @@
-import type * as Models from './models';
-import type * as Parameters from './parameters';
-import type { Client } from '../clients';
-import type { Callback } from '../callback';
-import type { RequestConfig } from '../requestConfig';
-
-export class Template {
-  constructor(private client: Client) {}
-
-  /**
-   * Creates a new content template. Note, blueprint templates cannot be created via the REST API.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'Admin' permission for the space to create a
-   * space template or 'Confluence Administrator' global permission to create a global template.
-   */
-  async createContentTemplate(
-    parameters: Parameters.CreateContentTemplate | undefined,
-    callback: Callback,
-  ): Promise;
-  /**
-   * Creates a new content template. Note, blueprint templates cannot be created via the REST API.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'Admin' permission for the space to create a
-   * space template or 'Confluence Administrator' global permission to create a global template.
-   */
-  async createContentTemplate(
-    parameters?: Parameters.CreateContentTemplate,
-    callback?: never,
-  ): Promise;
-  async createContentTemplate(
-    parameters?: Parameters.CreateContentTemplate,
-    callback?: Callback,
-  ): Promise {
-    const config: RequestConfig = {
-      url: '/api/template',
-      method: 'POST',
-      data: {
-        name: parameters?.name,
-        templateType: parameters?.templateType,
-        body: parameters?.body,
-        description: parameters?.description,
-        labels: parameters?.labels,
-        space: parameters?.space,
-      },
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-
-  /**
-   * Updates a content template. Note, blueprint templates cannot be updated via the REST API.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'Admin' permission for the space to update a
-   * space template or 'Confluence Administrator' global permission to update a global template.
-   */
-  async updateContentTemplate(
-    parameters: Parameters.UpdateContentTemplate | undefined,
-    callback: Callback,
-  ): Promise;
-  /**
-   * Updates a content template. Note, blueprint templates cannot be updated via the REST API.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'Admin' permission for the space to update a
-   * space template or 'Confluence Administrator' global permission to update a global template.
-   */
-  async updateContentTemplate(
-    parameters?: Parameters.UpdateContentTemplate,
-    callback?: never,
-  ): Promise;
-  async updateContentTemplate(
-    parameters?: Parameters.UpdateContentTemplate,
-    callback?: Callback,
-  ): Promise {
-    const config: RequestConfig = {
-      url: '/api/template',
-      method: 'PUT',
-      data: {
-        templateId: parameters?.templateId,
-        name: parameters?.name,
-        templateType: parameters?.templateType,
-        body: parameters?.body,
-        description: parameters?.description,
-        labels: parameters?.labels,
-        space: parameters?.space,
-      },
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-
-  /**
-   * Returns all templates provided by blueprints. Use this method to retrieve all global blueprint templates or all
-   * blueprint templates in a space.
-   *
-   * Note, all global blueprints are inherited by each space. Space blueprints can be customised without affecting the
-   * global blueprints.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'View' permission for the space to view
-   * blueprints for the space and permission to access the Confluence site ('Can use' global permission) to view global
-   * blueprints.
-   */
-  async getBlueprintTemplates(
-    parameters: Parameters.GetBlueprintTemplates | undefined,
-    callback: Callback,
-  ): Promise;
-  /**
-   * Returns all templates provided by blueprints. Use this method to retrieve all global blueprint templates or all
-   * blueprint templates in a space.
-   *
-   * Note, all global blueprints are inherited by each space. Space blueprints can be customised without affecting the
-   * global blueprints.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'View' permission for the space to view
-   * blueprints for the space and permission to access the Confluence site ('Can use' global permission) to view global
-   * blueprints.
-   */
-  async getBlueprintTemplates(
-    parameters?: Parameters.GetBlueprintTemplates,
-    callback?: never,
-  ): Promise;
-  async getBlueprintTemplates(
-    parameters?: Parameters.GetBlueprintTemplates,
-    callback?: Callback,
-  ): Promise {
-    const config: RequestConfig = {
-      url: '/api/template/blueprint',
-      method: 'GET',
-      params: {
-        spaceKey: parameters?.spaceKey,
-        start: parameters?.start,
-        limit: parameters?.limit,
-        expand: parameters?.expand,
-      },
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-
-  /**
-   * Returns all content templates. Use this method to retrieve all global content templates or all content templates in
-   * a space.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'View' permission for the space to view
-   * space templates and permission to access the Confluence site ('Can use' global permission) to view global
-   * templates.
-   */
-  async getContentTemplates(
-    parameters: Parameters.GetContentTemplates | undefined,
-    callback: Callback,
-  ): Promise;
-  /**
-   * Returns all content templates. Use this method to retrieve all global content templates or all content templates in
-   * a space.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'View' permission for the space to view
-   * space templates and permission to access the Confluence site ('Can use' global permission) to view global
-   * templates.
-   */
-  async getContentTemplates(
-    parameters?: Parameters.GetContentTemplates,
-    callback?: never,
-  ): Promise;
-  async getContentTemplates(
-    parameters?: Parameters.GetContentTemplates,
-    callback?: Callback,
-  ): Promise {
-    const config: RequestConfig = {
-      url: '/api/template/page',
-      method: 'GET',
-      params: {
-        spaceKey: parameters?.spaceKey,
-        start: parameters?.start,
-        limit: parameters?.limit,
-        expand: parameters?.expand,
-      },
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-
-  /**
-   * Returns a content template. This includes information about template, like the name, the space or blueprint that
-   * the template is in, the body of the template, and more.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'View' permission for the space to view
-   * space templates and permission to access the Confluence site ('Can use' global permission) to view global
-   * templates.
-   */
-  async getContentTemplate(
-    parameters: Parameters.GetContentTemplate,
-    callback: Callback,
-  ): Promise;
-  /**
-   * Returns a content template. This includes information about template, like the name, the space or blueprint that
-   * the template is in, the body of the template, and more.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'View' permission for the space to view
-   * space templates and permission to access the Confluence site ('Can use' global permission) to view global
-   * templates.
-   */
-  async getContentTemplate(
-    parameters: Parameters.GetContentTemplate,
-    callback?: never,
-  ): Promise;
-  async getContentTemplate(
-    parameters: Parameters.GetContentTemplate,
-    callback?: Callback,
-  ): Promise {
-    const config: RequestConfig = {
-      url: `/api/template/${parameters.contentTemplateId}`,
-      method: 'GET',
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-
-  /**
-   * Deletes a template. This results in different actions depending on the type of template:
-   *
-   * - If the template is a content template, it is deleted.
-   * - If the template is a modified space-level blueprint template, it reverts to the template inherited from the
-   *   global-level blueprint template.
-   * - If the template is a modified global-level blueprint template, it reverts to the default global-level blueprint
-   *   template.
-   *
-   * Note, unmodified blueprint templates cannot be deleted.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'Admin' permission for the space to delete a
-   * space template or 'Confluence Administrator' global permission to delete a global template.
-   */
-  async removeTemplate(parameters: Parameters.RemoveTemplate, callback: Callback): Promise;
-  /**
-   * Deletes a template. This results in different actions depending on the type of template:
-   *
-   * - If the template is a content template, it is deleted.
-   * - If the template is a modified space-level blueprint template, it reverts to the template inherited from the
-   *   global-level blueprint template.
-   * - If the template is a modified global-level blueprint template, it reverts to the default global-level blueprint
-   *   template.
-   *
-   * Note, unmodified blueprint templates cannot be deleted.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'Admin' permission for the space to delete a
-   * space template or 'Confluence Administrator' global permission to delete a global template.
-   */
-  async removeTemplate(parameters: Parameters.RemoveTemplate, callback?: never): Promise;
-  async removeTemplate(parameters: Parameters.RemoveTemplate, callback?: Callback): Promise {
-    const config: RequestConfig = {
-      url: `/api/template/${parameters.contentTemplateId}`,
-      method: 'DELETE',
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-}
diff --git a/src/api/themes.ts b/src/api/themes.ts
deleted file mode 100644
index b95f09e4..00000000
--- a/src/api/themes.ts
+++ /dev/null
@@ -1,155 +0,0 @@
-import type * as Models from './models';
-import type * as Parameters from './parameters';
-import type { Client } from '../clients';
-import type { Callback } from '../callback';
-import type { RequestConfig } from '../requestConfig';
-
-export class Themes {
-  constructor(private client: Client) {}
-
-  /**
-   * Returns all themes, not including the default theme.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: None
-   */
-  async getThemes(
-    parameters: Parameters.GetThemes | undefined,
-    callback: Callback,
-  ): Promise;
-  /**
-   * Returns all themes, not including the default theme.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: None
-   */
-  async getThemes(parameters?: Parameters.GetThemes, callback?: never): Promise;
-  async getThemes(parameters?: Parameters.GetThemes, callback?: Callback): Promise {
-    const config: RequestConfig = {
-      url: '/api/settings/theme',
-      method: 'GET',
-      params: {
-        start: parameters?.start,
-        limit: parameters?.limit,
-      },
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-
-  /**
-   * Returns the globally assigned theme.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: None
-   */
-  async getGlobalTheme(callback: Callback): Promise;
-  /**
-   * Returns the globally assigned theme.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: None
-   */
-  async getGlobalTheme(callback?: never): Promise;
-  async getGlobalTheme(callback?: Callback): Promise {
-    const config: RequestConfig = {
-      url: '/api/settings/theme/selected',
-      method: 'GET',
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-
-  /**
-   * Returns a theme. This includes information about the theme name, description, and icon.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: None
-   */
-  async getTheme(parameters: Parameters.GetTheme, callback: Callback): Promise;
-  /**
-   * Returns a theme. This includes information about the theme name, description, and icon.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: None
-   */
-  async getTheme(parameters: Parameters.GetTheme, callback?: never): Promise;
-  async getTheme(parameters: Parameters.GetTheme, callback?: Callback): Promise {
-    const config: RequestConfig = {
-      url: `/api/settings/theme/${parameters.themeKey}`,
-      method: 'GET',
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-
-  /**
-   * Returns the theme selected for a space, if one is set. If no space theme is set, this means that the space is
-   * inheriting the global look and feel settings.
-   *
-   * **[Permissions required](https://confluence.atlassian.com/x/_AozKw)**: ‘View’ permission for the space.
-   */
-  async getSpaceTheme(parameters: Parameters.GetSpaceTheme, callback: Callback): Promise;
-  /**
-   * Returns the theme selected for a space, if one is set. If no space theme is set, this means that the space is
-   * inheriting the global look and feel settings.
-   *
-   * **[Permissions required](https://confluence.atlassian.com/x/_AozKw)**: ‘View’ permission for the space.
-   */
-  async getSpaceTheme(parameters: Parameters.GetSpaceTheme, callback?: never): Promise;
-  async getSpaceTheme(
-    parameters: Parameters.GetSpaceTheme,
-    callback?: Callback,
-  ): Promise {
-    const config: RequestConfig = {
-      url: `/api/space/${parameters.spaceKey}/theme`,
-      method: 'GET',
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-
-  /**
-   * Sets the theme for a space. Note, if you want to reset the space theme to the default Confluence theme, use the
-   * 'Reset space theme' method instead of this method.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'Admin' permission for the space.
-   */
-  async setSpaceTheme(parameters: Parameters.SetSpaceTheme, callback: Callback): Promise;
-  /**
-   * Sets the theme for a space. Note, if you want to reset the space theme to the default Confluence theme, use the
-   * 'Reset space theme' method instead of this method.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'Admin' permission for the space.
-   */
-  async setSpaceTheme(parameters: Parameters.SetSpaceTheme, callback?: never): Promise;
-  async setSpaceTheme(
-    parameters: Parameters.SetSpaceTheme,
-    callback?: Callback,
-  ): Promise {
-    const config: RequestConfig = {
-      url: `/api/space/${parameters.spaceKey}/theme`,
-      method: 'PUT',
-      data: {
-        themeKey: parameters.themeKey,
-      },
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-
-  /**
-   * Resets the space theme. This means that the space will inherit the global look and feel settings
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'Admin' permission for the space.
-   */
-  async resetSpaceTheme(parameters: Parameters.ResetSpaceTheme, callback: Callback): Promise;
-  /**
-   * Resets the space theme. This means that the space will inherit the global look and feel settings
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'Admin' permission for the space.
-   */
-  async resetSpaceTheme(parameters: Parameters.ResetSpaceTheme, callback?: never): Promise;
-  async resetSpaceTheme(parameters: Parameters.ResetSpaceTheme, callback?: Callback): Promise {
-    const config: RequestConfig = {
-      url: `/api/space/${parameters.spaceKey}/theme`,
-      method: 'DELETE',
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-}
diff --git a/src/api/userProperties.ts b/src/api/userProperties.ts
deleted file mode 100644
index a5fcba89..00000000
--- a/src/api/userProperties.ts
+++ /dev/null
@@ -1,185 +0,0 @@
-import type * as Models from './models';
-import type * as Parameters from './parameters';
-import type { Client } from '../clients';
-import type { Callback } from '../callback';
-import type { RequestConfig } from '../requestConfig';
-
-export class UserProperties {
-  constructor(private client: Client) {}
-
-  /**
-   * Returns the properties for a user as list of property keys. For more information about user properties, see
-   * [Confluence entity properties](https://developer.atlassian.com/cloud/confluence/confluence-entity-properties/).
-   * `Note`, these properties stored against a user are on a Confluence site level and not space/content level.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to access the Confluence site
-   * ('Can use' global permission).
-   */
-  async getUserProperties(
-    parameters: Parameters.GetUserProperties,
-    callback: Callback,
-  ): Promise;
-  /**
-   * Returns the properties for a user as list of property keys. For more information about user properties, see
-   * [Confluence entity properties](https://developer.atlassian.com/cloud/confluence/confluence-entity-properties/).
-   * `Note`, these properties stored against a user are on a Confluence site level and not space/content level.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to access the Confluence site
-   * ('Can use' global permission).
-   */
-  async getUserProperties(
-    parameters: Parameters.GetUserProperties,
-    callback?: never,
-  ): Promise;
-  async getUserProperties(
-    parameters: Parameters.GetUserProperties,
-    callback?: Callback,
-  ): Promise {
-    const config: RequestConfig = {
-      url: `/api/user/${parameters.userId}/property`,
-      method: 'GET',
-      params: {
-        start: parameters.start,
-        limit: parameters.limit,
-      },
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-
-  /**
-   * Returns the property corresponding to `key` for a user. For more information about user properties, see [Confluence
-   * entity properties](https://developer.atlassian.com/cloud/confluence/confluence-entity-properties/). `Note`, these
-   * properties stored against a user are on a Confluence site level and not space/content level.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to access the Confluence site
-   * ('Can use' global permission).
-   */
-  async getUserProperty(
-    parameters: Parameters.GetUserProperty,
-    callback: Callback,
-  ): Promise;
-  /**
-   * Returns the property corresponding to `key` for a user. For more information about user properties, see [Confluence
-   * entity properties](https://developer.atlassian.com/cloud/confluence/confluence-entity-properties/). `Note`, these
-   * properties stored against a user are on a Confluence site level and not space/content level.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to access the Confluence site
-   * ('Can use' global permission).
-   */
-  async getUserProperty(parameters: Parameters.GetUserProperty, callback?: never): Promise;
-  async getUserProperty(
-    parameters: Parameters.GetUserProperty,
-    callback?: Callback,
-  ): Promise {
-    const config: RequestConfig = {
-      url: `/api/user/${parameters.userId}/property/${parameters.key}`,
-      method: 'GET',
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-
-  /**
-   * Creates a property for a user. For more information about user properties, see [Confluence entity properties]
-   * (https://developer.atlassian.com/cloud/confluence/confluence-entity-properties/). `Note`, these properties stored
-   * against a user are on a Confluence site level and not space/content level.
-   *
-   * `Note:` the number of properties which could be created per app in a tenant for each user might be restricted by
-   * fixed system limits. **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to access
-   * the Confluence site ('Can use' global permission).
-   */
-  async createUserProperty(
-    parameters: Parameters.CreateUserProperty,
-    callback: Callback,
-  ): Promise;
-  /**
-   * Creates a property for a user. For more information about user properties, see [Confluence entity properties]
-   * (https://developer.atlassian.com/cloud/confluence/confluence-entity-properties/). `Note`, these properties stored
-   * against a user are on a Confluence site level and not space/content level.
-   *
-   * `Note:` the number of properties which could be created per app in a tenant for each user might be restricted by
-   * fixed system limits. **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to access
-   * the Confluence site ('Can use' global permission).
-   */
-  async createUserProperty(parameters: Parameters.CreateUserProperty, callback?: never): Promise;
-  async createUserProperty(
-    parameters: Parameters.CreateUserProperty,
-    callback?: Callback,
-  ): Promise {
-    const config: RequestConfig = {
-      url: `/api/user/${parameters.userId}/property/${parameters.key}`,
-      method: 'POST',
-      data: {
-        value: parameters.value,
-      },
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-
-  /**
-   * Updates a property for the given user. Note, you cannot update the key of a user property, only the value. For more
-   * information about user properties, see [Confluence entity
-   * properties](https://developer.atlassian.com/cloud/confluence/confluence-entity-properties/). `Note`, these
-   * properties stored against a user are on a Confluence site level and not space/content level.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to access the Confluence site
-   * ('Can use' global permission).
-   */
-  async updateUserProperty(parameters: Parameters.UpdateUserProperty, callback: Callback): Promise;
-  /**
-   * Updates a property for the given user. Note, you cannot update the key of a user property, only the value. For more
-   * information about user properties, see [Confluence entity
-   * properties](https://developer.atlassian.com/cloud/confluence/confluence-entity-properties/). `Note`, these
-   * properties stored against a user are on a Confluence site level and not space/content level.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to access the Confluence site
-   * ('Can use' global permission).
-   */
-  async updateUserProperty(parameters: Parameters.UpdateUserProperty, callback?: never): Promise;
-  async updateUserProperty(
-    parameters: Parameters.UpdateUserProperty,
-    callback?: Callback,
-  ): Promise {
-    const config: RequestConfig = {
-      url: `/api/user/${parameters.userId}/property/${parameters.key}`,
-      method: 'PUT',
-      data: {
-        value: parameters.value,
-      },
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-
-  /**
-   * Deletes a property for the given user. For more information about user properties, see [Confluence entity
-   * properties](https://developer.atlassian.com/cloud/confluence/confluence-entity-properties/). `Note`, these
-   * properties stored against a user are on a Confluence site level and not space/content level.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to access the Confluence site
-   * ('Can use' global permission).
-   */
-  async deleteUserProperty(parameters: Parameters.DeleteUserProperty, callback: Callback): Promise;
-  /**
-   * Deletes a property for the given user. For more information about user properties, see [Confluence entity
-   * properties](https://developer.atlassian.com/cloud/confluence/confluence-entity-properties/). `Note`, these
-   * properties stored against a user are on a Confluence site level and not space/content level.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to access the Confluence site
-   * ('Can use' global permission).
-   */
-  async deleteUserProperty(parameters: Parameters.DeleteUserProperty, callback?: never): Promise;
-  async deleteUserProperty(
-    parameters: Parameters.DeleteUserProperty,
-    callback?: Callback,
-  ): Promise {
-    const config: RequestConfig = {
-      url: `/api/user/${parameters.userId}/property/${parameters.key}`,
-      method: 'DELETE',
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-}
diff --git a/src/api/users.ts b/src/api/users.ts
deleted file mode 100644
index a2c97e29..00000000
--- a/src/api/users.ts
+++ /dev/null
@@ -1,323 +0,0 @@
-import type * as Models from './models';
-import type * as Parameters from './parameters';
-import type { Client } from '../clients';
-import type { Callback } from '../callback';
-import type { RequestConfig } from '../requestConfig';
-
-export class Users {
-  constructor(private client: Client) {}
-
-  /**
-   * Returns a user. This includes information about the user, such as the display name, account ID, profile picture,
-   * and more. The information returned may be restricted by the user's profile visibility settings.
-   *
-   * **Note:** to add, edit, or delete users in your organization, see the [user management REST
-   * API](/cloud/admin/user-management/about/).
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to access the Confluence site
-   * ('Can use' global permission).
-   */
-  async getUser(parameters: Parameters.GetUser, callback: Callback): Promise;
-  /**
-   * Returns a user. This includes information about the user, such as the display name, account ID, profile picture,
-   * and more. The information returned may be restricted by the user's profile visibility settings.
-   *
-   * **Note:** to add, edit, or delete users in your organization, see the [user management REST
-   * API](/cloud/admin/user-management/about/).
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to access the Confluence site
-   * ('Can use' global permission).
-   */
-  async getUser(parameters: Parameters.GetUser, callback?: never): Promise;
-  async getUser(parameters: Parameters.GetUser, callback?: Callback): Promise {
-    const config: RequestConfig = {
-      url: '/api/user',
-      method: 'GET',
-      params: {
-        key: parameters.key,
-        username: parameters.username,
-        accountId: parameters.accountId,
-        expand: parameters.expand,
-      },
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-
-  /**
-   * Returns information about how anonymous users are represented, like the profile picture and display name.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to access the Confluence site
-   * ('Can use' global permission).
-   */
-  async getAnonymousUser(
-    parameters: Parameters.GetAnonymousUser | undefined,
-    callback: Callback,
-  ): Promise;
-  /**
-   * Returns information about how anonymous users are represented, like the profile picture and display name.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to access the Confluence site
-   * ('Can use' global permission).
-   */
-  async getAnonymousUser(
-    parameters?: Parameters.GetAnonymousUser,
-    callback?: never,
-  ): Promise;
-  async getAnonymousUser(
-    parameters?: Parameters.GetAnonymousUser,
-    callback?: Callback,
-  ): Promise {
-    const config: RequestConfig = {
-      url: '/api/user/anonymous',
-      method: 'GET',
-      params: {
-        expand: parameters?.expand,
-      },
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-
-  /**
-   * Returns the currently logged-in user. This includes information about the user, like the display name, userKey,
-   * account ID, profile picture, and more.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to access the Confluence site
-   * ('Can use' global permission).
-   */
-  async getCurrentUser(
-    parameters: Parameters.GetCurrentUser | undefined,
-    callback: Callback,
-  ): Promise;
-  /**
-   * Returns the currently logged-in user. This includes information about the user, like the display name, userKey,
-   * account ID, profile picture, and more.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to access the Confluence site
-   * ('Can use' global permission).
-   */
-  async getCurrentUser(parameters?: Parameters.GetCurrentUser, callback?: never): Promise;
-  async getCurrentUser(
-    parameters?: Parameters.GetCurrentUser,
-    callback?: Callback,
-  ): Promise {
-    const config: RequestConfig = {
-      url: '/api/user/current',
-      method: 'GET',
-      params: {
-        expand: parameters?.expand,
-      },
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-
-  /**
-   * Returns the groups that a user is a member of.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to access the Confluence site
-   * ('Can use' global permission).
-   */
-  async getGroupMembershipsForUser(
-    parameters: Parameters.GetGroupMembershipsForUser,
-    callback: Callback,
-  ): Promise;
-  /**
-   * Returns the groups that a user is a member of.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to access the Confluence site
-   * ('Can use' global permission).
-   */
-  async getGroupMembershipsForUser(
-    parameters: Parameters.GetGroupMembershipsForUser,
-    callback?: never,
-  ): Promise;
-  async getGroupMembershipsForUser(
-    parameters: Parameters.GetGroupMembershipsForUser,
-    callback?: Callback,
-  ): Promise {
-    const config: RequestConfig = {
-      url: '/api/user/memberof',
-      method: 'GET',
-      params: {
-        key: parameters.key,
-        username: parameters.username,
-        accountId: parameters.accountId,
-        start: parameters.start,
-        limit: parameters.limit,
-      },
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-
-  /**
-   * Returns user details for the ids provided in the request. Currently this API returns a maximum of 100 results. If
-   * more than 100 account ids are passed in, then the first 100 will be returned.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to access the Confluence site
-   * ('Can use' global permission).
-   */
-  async getBulkUserLookup(
-    parameters: Parameters.GetBulkUserLookup,
-    callback: Callback,
-  ): Promise;
-  /**
-   * Returns user details for the ids provided in the request. Currently this API returns a maximum of 100 results. If
-   * more than 100 account ids are passed in, then the first 100 will be returned.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to access the Confluence site
-   * ('Can use' global permission).
-   */
-  async getBulkUserLookup(
-    parameters: Parameters.GetBulkUserLookup,
-    callback?: never,
-  ): Promise;
-  async getBulkUserLookup(
-    parameters: Parameters.GetBulkUserLookup,
-    callback?: Callback,
-  ): Promise {
-    const config: RequestConfig = {
-      url: '/api/user/bulk',
-      method: 'GET',
-      params: {
-        accountId: parameters.accountId,
-        expand: parameters.expand,
-        limit: parameters.limit,
-      },
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-
-  /**
-   * Returns a user's email address regardless of the user’s profile visibility settings. For Connect apps, this API is
-   * only available to apps approved by Atlassian, according to these
-   * [guidelines](https://community.developer.atlassian.com/t/guidelines-for-requesting-access-to-email-address/27603).
-   * For Forge apps, this API only supports access via asApp() requests.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to access the Confluence site
-   * ('Can use' global permission).
-   */
-  async getPrivacyUnsafeUserEmail(
-    parameters: Parameters.GetPrivacyUnsafeUserEmail,
-    callback: Callback,
-  ): Promise;
-  /**
-   * Returns a user's email address regardless of the user’s profile visibility settings. For Connect apps, this API is
-   * only available to apps approved by Atlassian, according to these
-   * [guidelines](https://community.developer.atlassian.com/t/guidelines-for-requesting-access-to-email-address/27603).
-   * For Forge apps, this API only supports access via asApp() requests.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to access the Confluence site
-   * ('Can use' global permission).
-   */
-  async getPrivacyUnsafeUserEmail(
-    parameters: Parameters.GetPrivacyUnsafeUserEmail,
-    callback?: never,
-  ): Promise;
-  async getPrivacyUnsafeUserEmail(
-    parameters: Parameters.GetPrivacyUnsafeUserEmail,
-    callback?: Callback,
-  ): Promise {
-    const config: RequestConfig = {
-      url: '/api/user/email',
-      method: 'GET',
-      params: {
-        accountId: parameters.accountId,
-      },
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-
-  /**
-   * Returns a user's email address regardless of the user’s profile visibility settings. For Connect apps, this API is
-   * only available to apps approved by Atlassian, according to these
-   * [guidelines](https://community.developer.atlassian.com/t/guidelines-for-requesting-access-to-email-address/27603).
-   * For Forge apps, this API only supports access via asApp() requests.
-   *
-   * Any accounts which are not available will not be included in the result.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to access the Confluence site
-   * ('Can use' global permission).
-   */
-  async getPrivacyUnsafeUserEmailBulk(
-    parameters: Parameters.GetPrivacyUnsafeUserEmailBulk,
-    callback: Callback,
-  ): Promise;
-  /**
-   * Returns a user's email address regardless of the user’s profile visibility settings. For Connect apps, this API is
-   * only available to apps approved by Atlassian, according to these
-   * [guidelines](https://community.developer.atlassian.com/t/guidelines-for-requesting-access-to-email-address/27603).
-   * For Forge apps, this API only supports access via asApp() requests.
-   *
-   * Any accounts which are not available will not be included in the result.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to access the Confluence site
-   * ('Can use' global permission).
-   */
-  async getPrivacyUnsafeUserEmailBulk(
-    parameters: Parameters.GetPrivacyUnsafeUserEmailBulk,
-    callback?: never,
-  ): Promise;
-  async getPrivacyUnsafeUserEmailBulk(
-    parameters: Parameters.GetPrivacyUnsafeUserEmailBulk,
-    callback?: Callback,
-  ): Promise {
-    const config: RequestConfig = {
-      url: '/api/user/email/bulk',
-      method: 'GET',
-      params: {
-        accountId: parameters.accountId,
-      },
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-
-  /**
-   * Returns the accountIds for the users specified in the key or username parameters. Note that multiple key and
-   * username parameters can be specified.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'Confluence Administrator' global permission
-   * if specifying a user, otherwise permission to access the Confluence site ('Can use' global permission).
-   *
-   * @deprecated Will be removed in next major version.
-   */
-  async getBulkUserMigration(
-    parameters: Parameters.GetBulkUserMigration,
-    callback: Callback,
-  ): Promise;
-  /**
-   * Returns the accountIds for the users specified in the key or username parameters. Note that multiple key and
-   * username parameters can be specified.
-   *
-   * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'Confluence Administrator' global permission
-   * if specifying a user, otherwise permission to access the Confluence site ('Can use' global permission).
-   *
-   * @deprecated Will be removed in next major version.
-   */
-  async getBulkUserMigration(
-    parameters: Parameters.GetBulkUserMigration,
-    callback?: never,
-  ): Promise;
-  async getBulkUserMigration(
-    parameters: Parameters.GetBulkUserMigration,
-    callback?: Callback,
-  ): Promise {
-    const config: RequestConfig = {
-      url: '/api/user/bulk/migration',
-      method: 'GET',
-      params: {
-        key: parameters.key,
-        username: parameters.username,
-        start: parameters.start,
-        limit: parameters.limit,
-      },
-    };
-
-    return this.client.sendRequest(config, callback);
-  }
-}
diff --git a/src/callback.ts b/src/callback.ts
deleted file mode 100644
index 6d1aedd4..00000000
--- a/src/callback.ts
+++ /dev/null
@@ -1,3 +0,0 @@
-import type { AxiosError } from 'axios';
-
-export type Callback = (err: AxiosError | null, data?: T) => void;
diff --git a/src/clients/baseClient.ts b/src/clients/baseClient.ts
deleted file mode 100644
index fefa64f8..00000000
--- a/src/clients/baseClient.ts
+++ /dev/null
@@ -1,136 +0,0 @@
-/* eslint-disable @typescript-eslint/no-explicit-any,@typescript-eslint/no-unnecessary-condition */
-import type { AxiosInstance } from 'axios';
-import axios from 'axios';
-import { getAuthenticationToken } from '~/services';
-import type { Callback } from '~/callback';
-import type { Client } from './client';
-import { ConfigSchema, type Config, type Error as ConfluenceError } from '~/config';
-import type { RequestConfig } from '~/requestConfig';
-import { ZodError } from 'zod';
-
-const ATLASSIAN_TOKEN_CHECK_FLAG = 'X-Atlassian-Token';
-const ATLASSIAN_TOKEN_CHECK_NOCHECK_VALUE = 'no-check';
-
-export class BaseClient implements Client {
-  #instance: AxiosInstance | undefined;
-
-  constructor(protected readonly config: Config) {
-    this.config.apiPrefix = this.config.apiPrefix || '/wiki/rest/';
-
-    try {
-      this.config = ConfigSchema.parse(this.config);
-    } catch (e) {
-      if (e instanceof ZodError && e.errors[0].code === 'invalid_string') {
-        throw new Error(e.errors[0].message);
-      }
-
-      throw e;
-    }
-  }
-
-  protected paramSerializer(parameters: Record): string {
-    const parts: string[] = [];
-
-    Object.entries(parameters).forEach(([key, value]) => {
-      if (value === null || typeof value === 'undefined') {
-        return;
-      }
-
-      if (Array.isArray(value)) {
-        value = value.join(',');
-      }
-
-      if (value instanceof Date) {
-        value = value.toISOString();
-      } else if (value !== null && typeof value === 'object') {
-        value = JSON.stringify(value);
-      } else if (value instanceof Function) {
-        const part = value();
-
-        return part && parts.push(part);
-      }
-
-      parts.push(`${this.encode(key)}=${this.encode(value)}`);
-    });
-
-    return parts.join('&');
-  }
-
-  protected encode(value: string) {
-    return encodeURIComponent(value)
-      .replace(/%3A/gi, ':')
-      .replace(/%24/g, '$')
-      .replace(/%2C/gi, ',')
-      .replace(/%20/g, '+')
-      .replace(/%5B/gi, '[')
-      .replace(/%5D/gi, ']');
-  }
-
-  protected removeUndefinedProperties(obj: Record): Record {
-    return Object.entries(obj)
-      .filter(([, value]) => typeof value !== 'undefined')
-      .reduce((accumulator, [key, value]) => ({ ...accumulator, [key]: value }), {});
-  }
-
-  private get instance() {
-    if (this.#instance) {
-      return this.#instance;
-    }
-
-    this.#instance = axios.create({
-      paramsSerializer: this.paramSerializer.bind(this),
-      ...this.config.baseRequestConfig,
-      baseURL: `${this.config.host}${this.config.apiPrefix}`,
-      headers: this.removeUndefinedProperties({
-        [ATLASSIAN_TOKEN_CHECK_FLAG]: this.config.noCheckAtlassianToken
-          ? ATLASSIAN_TOKEN_CHECK_NOCHECK_VALUE
-          : undefined,
-        ...this.config.baseRequestConfig?.headers,
-      }),
-    });
-
-    return this.#instance;
-  }
-
-  async sendRequest(requestConfig: RequestConfig, callback: never): Promise;
-  async sendRequest(requestConfig: RequestConfig, callback: Callback): Promise;
-  async sendRequest(requestConfig: RequestConfig, callback: Callback | never): Promise {
-    try {
-      const modifiedRequestConfig = {
-        ...requestConfig,
-        headers: this.removeUndefinedProperties({
-          Authorization: await getAuthenticationToken(this.config.authentication, {
-            baseURL: this.config.host,
-            url: this.instance.getUri(requestConfig),
-            method: requestConfig.method!,
-          }),
-          ...requestConfig.headers,
-        }),
-      };
-
-      const response = await this.instance.request(modifiedRequestConfig);
-
-      const callbackResponseHandler = callback && ((data: T): void => callback(null, data));
-      const defaultResponseHandler = (data: T): T => data;
-
-      const responseHandler = callbackResponseHandler ?? defaultResponseHandler;
-
-      this.config.middlewares?.onResponse?.(response.data);
-
-      return responseHandler(response.data);
-    } catch (e: any) {
-      const err = e.isAxiosError ? e.response.data : e;
-
-      const callbackErrorHandler = callback && ((error: ConfluenceError) => callback(error));
-      const defaultErrorHandler = (error: Error) => {
-        throw error;
-      };
-
-      const errorHandler = callbackErrorHandler ?? defaultErrorHandler;
-
-      this.config.middlewares?.onError?.(err);
-
-      return errorHandler(err);
-    }
-  }
-}
diff --git a/src/clients/client.ts b/src/clients/client.ts
deleted file mode 100644
index 1a7b0b37..00000000
--- a/src/clients/client.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-import type { Callback } from '../callback';
-import type { RequestConfig } from '../requestConfig';
-
-export interface Client {
-  sendRequest(requestConfig: RequestConfig, callback?: never): Promise;
-  sendRequest(requestConfig: RequestConfig, callback?: Callback): Promise;
-}
diff --git a/src/clients/confluenceClient.ts b/src/clients/confluenceClient.ts
deleted file mode 100644
index 2492e222..00000000
--- a/src/clients/confluenceClient.ts
+++ /dev/null
@@ -1,82 +0,0 @@
-import { BaseClient } from './baseClient';
-import type { Config } from '../config';
-import {
-  Analytics,
-  Audit,
-  Content,
-  ContentAttachments,
-  ContentBody,
-  ContentChildrenAndDescendants,
-  ContentComments,
-  ContentLabels,
-  ContentMacroBody,
-  ContentPermissions,
-  ContentProperties,
-  ContentRestrictions,
-  ContentStates,
-  ContentVersions,
-  ContentWatches,
-  DynamicModules,
-  Experimental,
-  Group,
-  InlineTasks,
-  LabelInfo,
-  LongRunningTask,
-  Relation,
-  Search,
-  Settings,
-  Space,
-  SpacePermissions,
-  SpaceProperties,
-  SpaceSettings,
-  Template,
-  Themes,
-  Users,
-  UserProperties,
-} from '../api';
-
-export class ConfluenceClient extends BaseClient {
-  constructor(config: Config) {
-    super({
-      ...config,
-      apiPrefix: config.apiPrefix ?? '/wiki/rest',
-    });
-  }
-
-  analytics = new Analytics(this);
-  audit = new Audit(this);
-  content = new Content(this);
-  contentAttachments = new ContentAttachments(this);
-  contentBody = new ContentBody(this);
-  contentChildrenAndDescendants = new ContentChildrenAndDescendants(this);
-  /** @deprecated Will be removed in next major version. */
-  contentComments = new ContentComments(this);
-  contentLabels = new ContentLabels(this);
-  contentMacroBody = new ContentMacroBody(this);
-  contentPermissions = new ContentPermissions(this);
-  /** @deprecated Will be removed in next major version. */
-  contentProperties = new ContentProperties(this);
-  contentRestrictions = new ContentRestrictions(this);
-  contentStates = new ContentStates(this);
-  contentVersions = new ContentVersions(this);
-  contentWatches = new ContentWatches(this);
-  dynamicModules = new DynamicModules(this);
-  experimental = new Experimental(this);
-  group = new Group(this);
-  /** @deprecated Will be removed in next major version. */
-  inlineTasks = new InlineTasks(this);
-  labelInfo = new LabelInfo(this);
-  longRunningTask = new LongRunningTask(this);
-  relation = new Relation(this);
-  search = new Search(this);
-  settings = new Settings(this);
-  space = new Space(this);
-  spacePermissions = new SpacePermissions(this);
-  /** @deprecated Will be removed in next major version. */
-  spaceProperties = new SpaceProperties(this);
-  spaceSettings = new SpaceSettings(this);
-  template = new Template(this);
-  themes = new Themes(this);
-  users = new Users(this);
-  userProperties = new UserProperties(this);
-}
diff --git a/src/clients/index.ts b/src/clients/index.ts
deleted file mode 100644
index c538c529..00000000
--- a/src/clients/index.ts
+++ /dev/null
@@ -1,3 +0,0 @@
-export * from './baseClient';
-export * from './client';
-export * from './confluenceClient';
diff --git a/src/config.ts b/src/config.ts
deleted file mode 100644
index e7ef4313..00000000
--- a/src/config.ts
+++ /dev/null
@@ -1,75 +0,0 @@
-import { z } from 'zod';
-import type { AxiosError } from 'axios';
-
-/**
- * Basic authentication configuration using email and API token
- *
- * @see {@link https://support.atlassian.com/atlassian-account/docs/manage-api-tokens-for-your-atlassian-account/} for how to create API tokens
- */
-export const BasicSchema = z.strictObject({
-  basic: z.strictObject({
-    /** User's email associated with Atlassian account */
-    email: z.string().email(),
-    /**
-     * API token generated from Atlassian account settings
-     *
-     * @see {@link https://support.atlassian.com/atlassian-account/docs/manage-api-tokens-for-your-atlassian-account/} for how to create API tokens
-     */
-    apiToken: z.string().min(1, 'API token is required'),
-  }),
-});
-
-/** JWT authentication configuration */
-export const JWTSchema = z.strictObject({
-  jwt: z.strictObject({
-    /** The key from the app descriptor */
-    issuer: z.string(),
-    /** The shared secret key from app installation */
-    secret: z.string(),
-    /** Token expiry time (default: 180) */
-    expiryTimeSeconds: z.optional(z.number()),
-  }),
-});
-
-/** OAuth2 authentication configuration */
-export const OAuth2Schema = z.strictObject({
-  oauth2: z.strictObject({
-    /** OAuth2 access token */
-    accessToken: z.string(),
-  }),
-});
-
-/** Authentication configuration schema */
-export const AuthenticationSchema = z.union([BasicSchema, JWTSchema, OAuth2Schema]);
-
-/** Base request configuration */
-export const RequestConfigSchema = z.any();
-
-/** Middleware configuration schema */
-export const MiddlewaresSchema = z.object({
-  /** Error handler middleware */
-  onError: z.optional(z.function().args(z.any()).returns(z.void())),
-  /** Response handler middleware */
-  onResponse: z.optional(z.function().args(z.any()).returns(z.void())),
-});
-
-export const ConfigSchema = z.object({
-  host: z.string().url({
-    message:
-      'Couldn\'t parse the host URL. Perhaps you forgot to add \'http://\' or \'https://\' at the beginning of the URL?',
-  }),
-  baseRequestConfig: z.optional(RequestConfigSchema),
-  authentication: z.optional(AuthenticationSchema),
-  middlewares: z.optional(MiddlewaresSchema),
-  /** Adds `'X-Atlassian-Token': 'no-check'` to each request header */
-  noCheckAtlassianToken: z.optional(z.boolean()),
-  /** Prefix for all API routes. */
-  apiPrefix: z.optional(z.string()),
-});
-
-export type Config = z.infer;
-export type Authentication = z.infer;
-export type Basic = z.infer;
-export type JWT = z.infer;
-export type OAuth2 = z.infer;
-export type Error = AxiosError;
diff --git a/src/core/apiObject.ts b/src/core/apiObject.ts
new file mode 100644
index 00000000..556552cf
--- /dev/null
+++ b/src/core/apiObject.ts
@@ -0,0 +1,5 @@
+import { z, type ZodRawShape } from 'zod';
+
+export function apiObject(shape: Shape) {
+  return z.object(shape).loose();
+}
diff --git a/src/core/bodyToFetchBody.ts b/src/core/bodyToFetchBody.ts
new file mode 100644
index 00000000..aea16927
--- /dev/null
+++ b/src/core/bodyToFetchBody.ts
@@ -0,0 +1,65 @@
+function isAsyncIterable(value: unknown): value is AsyncIterable {
+  if (value == null) return false;
+
+  return typeof (value as { [Symbol.asyncIterator]?: unknown })[Symbol.asyncIterator] === 'function';
+}
+
+/**
+ * Whether the body carries its own encoding and must be handed to `fetch` untouched.
+ *
+ * A bare string is deliberately *not* one of these. These are JSON APIs, and the endpoints that take a lone string —
+ * an account id, a preference value — want it as a JSON string, quoted, under `application/json`. Treating it as a
+ * pre-encoded payload shipped it raw as `text/plain` and made those endpoints unreachable. Attachment content never
+ * arrives here as a string: the multipart builder normalizes it into `FormData` or a stream first.
+ */
+function isBinaryBody(body: unknown): boolean {
+  if (typeof FormData !== 'undefined' && body instanceof FormData) return true;
+
+  if (typeof URLSearchParams !== 'undefined' && body instanceof URLSearchParams) return true;
+
+  if (typeof Blob !== 'undefined' && body instanceof Blob) return true;
+
+  if (typeof ReadableStream !== 'undefined' && body instanceof ReadableStream) return true;
+
+  if (typeof ArrayBuffer !== 'undefined' && body instanceof ArrayBuffer) return true;
+
+  // Covers Node's Buffer too, which is a Uint8Array — naming it here would drag
+  // @types/node into the declaration and break browser consumers.
+  if (typeof ArrayBuffer !== 'undefined' && ArrayBuffer.isView(body as ArrayBufferView)) return true;
+
+  if (isAsyncIterable(body)) return true;
+
+  return false;
+}
+
+export function bodyToFetchBody(body: unknown): BodyInit | AsyncIterable {
+  if (isBinaryBody(body)) {
+    return body as BodyInit | AsyncIterable;
+  }
+
+  return JSON.stringify(body);
+}
+
+/**
+ * Whether to declare `application/json` for this request.
+ *
+ * Sent even when there is no body, for any method that could carry one. Some endpoints reject a bodyless `DELETE`
+ * with 415 unless the header is present — Jira's remote-link deletes do — and a `Content-Type` on an empty request is
+ * inert everywhere else. Binary and multipart bodies are excluded because they bring their own type, and `fetch` has
+ * to be left to set the multipart boundary itself.
+ */
+export function shouldSetJsonContentType(body: unknown, method?: string): boolean {
+  if (isBinaryBody(body)) return false;
+
+  if (body !== undefined && body !== null) return true;
+
+  const verb = (method ?? 'GET').toUpperCase();
+
+  return verb !== 'GET' && verb !== 'HEAD';
+}
+
+export function requiresDuplex(body: unknown): boolean {
+  if (typeof ReadableStream !== 'undefined' && body instanceof ReadableStream) return true;
+
+  return isAsyncIterable(body);
+}
diff --git a/src/core/createClient.ts b/src/core/createClient.ts
new file mode 100644
index 00000000..0d426d7c
--- /dev/null
+++ b/src/core/createClient.ts
@@ -0,0 +1,293 @@
+import { bodyToFetchBody, requiresDuplex, shouldSetJsonContentType } from './bodyToFetchBody.js';
+import type { Auth, ClientConfig, SendRequestOptions } from './schemas/index.js';
+import type { Client } from './interfaces/index.js';
+import type { OAuth2Manager } from './oauth/index.js';
+import {
+  createApiError,
+  isNetworkError,
+  SchemaMismatchError,
+  toNetworkError,
+  TRANSIENT_HTTP_STATUSES,
+} from './errors/index.js';
+import { BufferSchema } from './formData/index.js';
+import { buildUrlWithSearchParams } from './serializeSearchParams.js';
+import { clientConfigSchema } from './schemas/index.js';
+import { createOAuth2Manager } from './oauth/index.js';
+
+/**
+ * Whether this 401 means "missing scope" rather than "stale token".
+ *
+ * Reads a clone, so the body stays available for the error that gets thrown later.
+ */
+async function isScopeMismatchResponse(response: Response): Promise {
+  try {
+    return /scope does not match/i.test(await response.clone().text());
+  } catch {
+    return false;
+  }
+}
+
+/** A `Client` is anything with `sendRequest`; a `ClientConfig` never has one. */
+function isClient(value: ClientConfig | Client): value is Client {
+  return typeof (value as Client).sendRequest === 'function';
+}
+
+/**
+ * Base64 for the Basic auth header, the same way in every runtime.
+ *
+ * `btoa` alone mangles anything outside Latin-1, so the string is encoded to UTF-8 bytes first — a credential may well
+ * hold non-ASCII. Verified byte-identical to `Buffer.from(…).toString('base64')`.
+ */
+function base64Encode(value: string): string {
+  const bytes = new TextEncoder().encode(value);
+
+  let binary = '';
+
+  for (const byte of bytes) binary += String.fromCharCode(byte);
+
+  return btoa(binary);
+}
+
+async function getAuthHeaders(auth: Auth): Promise> {
+  if (auth.type === 'oauth2') {
+    // Handled by the manager, which owns refresh and expiry. Reaching here means
+    // the caller swapped in OAuth 2.0 through `getAuthOn401`, which cannot carry
+    // that state — so fall back to whatever static token was supplied.
+    return auth.accessToken ? { Authorization: `Bearer ${auth.accessToken}` } : {};
+  }
+
+  if (auth.type === 'basic') {
+    const encoded = base64Encode(`${auth.email}:${auth.apiToken}`);
+
+    return { Authorization: `Basic ${encoded}` };
+  }
+
+  if ('getToken' in auth) {
+    const token = await auth.getToken();
+
+    return { Authorization: `Bearer ${token}` };
+  }
+
+  return { Authorization: `Bearer ${auth.token}` };
+}
+
+/**
+ * Creates a low-level Confluence API client.
+ *
+ * The client carries only transport, auth and retry policy — it is version agnostic, so one instance drives both
+ * `confluence.js/v1` and `confluence.js/v2`.
+ *
+ * Prefer `createV1Client` / `createV2Client` from `confluence.js` unless you want the flat functions and a smaller
+ * bundle.
+ *
+ * @stable
+ */
+export function createClient(config: ClientConfig | Client): Client {
+  // Already a client: hand it straight back. This is what lets createV1Client and
+  // createV2Client share one instance — and with it one OAuth token. Building a
+  // client per factory would give each its own refresh cycle, and the first
+  // rotation would kill the other's refresh token.
+  if (isClient(config)) return config;
+
+  clientConfigSchema.parse(config);
+
+  const { host, auth, headers: configHeaders = {}, getAuthOn401, retry } = config;
+  const retryMaxAttempts = Math.max(1, retry?.maxAttempts ?? 1);
+  const retryInitialDelayMs = retry?.initialDelayMs ?? 500;
+  const retryBackoffFactor = retry?.backoffFactor ?? 2;
+
+  // One manager per client, so the refreshed token and the resolved cloud id are
+  // shared by every request instead of being rediscovered per call.
+  const oauth2Manager: OAuth2Manager | undefined = auth?.type === 'oauth2' ? createOAuth2Manager(auth) : undefined;
+
+  return {
+    async sendRequest(requestConfig: SendRequestOptions): Promise {
+      const path = requestConfig.url.startsWith('/') ? requestConfig.url : `/${requestConfig.url}`;
+      // Under OAuth 2.0 the gateway URL wins over `host`: a 3LO token is rejected
+      // on the site's own domain, so honouring `host` there would only produce 401s.
+      const effectiveHost = oauth2Manager ? await oauth2Manager.getBaseUrl() : host;
+      const normalizedHost =
+        effectiveHost && (effectiveHost.endsWith('/') ? effectiveHost.slice(0, -1) : effectiveHost);
+      const url = normalizedHost ? normalizedHost + path : requestConfig.url;
+      const fullUrl = buildUrlWithSearchParams(url, requestConfig.searchParams);
+
+      const rawBody = requestConfig.body;
+      const body = rawBody === undefined || rawBody === null ? undefined : bodyToFetchBody(rawBody);
+
+      const doRequest = async (authHeaders: Record): Promise => {
+        const headers: Record = {
+          Accept: 'application/json',
+          ...(shouldSetJsonContentType(rawBody, requestConfig.method) ? { 'Content-Type': 'application/json' } : {}),
+          ...authHeaders,
+          ...configHeaders,
+          ...requestConfig.headers,
+        };
+
+        const init: RequestInit & { duplex?: 'half' } = {
+          method: requestConfig.method,
+          headers: Object.keys(headers).length > 0 ? headers : undefined,
+          body: body as BodyInit,
+        };
+
+        if (requiresDuplex(rawBody)) {
+          init.duplex = 'half';
+        }
+
+        return fetch(fullUrl, init);
+      };
+
+      const currentAuthHeaders = async (): Promise> => {
+        if (oauth2Manager) return { Authorization: await oauth2Manager.getAuthorizationHeader() };
+
+        return auth ? getAuthHeaders(auth) : {};
+      };
+
+      let derivedAuthHeaders = await currentAuthHeaders();
+      let response: Response;
+      let delayMs = retryInitialDelayMs;
+      let networkAttempt = 0;
+      let reauthenticated = false;
+      // Retry loop: covers transport-layer failures (TLS/socket/DNS) and
+      // 502/503/504 upstream failures. Auth re-derivation on 401 happens once
+      // per response cycle, inside the loop, so a refreshed token survives
+      // subsequent transient retries.
+
+      // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- intentional retry loop
+      while (true) {
+        try {
+          response = await doRequest(derivedAuthHeaders);
+        } catch (err) {
+          // A bad URL also rejects here, as a TypeError with no code — wrapping it
+          // keeps one catch surface, and `transient: false` keeps it out of retries.
+          const networkError = isNetworkError(err) ? err : toNetworkError(err, fullUrl);
+
+          if (networkAttempt + 1 < retryMaxAttempts && networkError.transient) {
+            networkAttempt += 1;
+            await new Promise(resolve => setTimeout(resolve, delayMs));
+            delayMs = Math.round(delayMs * retryBackoffFactor);
+            continue;
+          }
+
+          throw networkError;
+        }
+
+        // Re-authentication is attempted at most once per request: a second 401
+        // means the fresh credentials are themselves rejected, and retrying that
+        // forever would turn a bad token into an infinite loop.
+        //
+        // A missing scope also answers 401, and refreshing cannot mint a scope the
+        // app never asked for. Worse, each pointless refresh rotates the refresh
+        // token, so a loop of scope errors would churn credentials for nothing.
+        if (response.status === 401 && !reauthenticated && !(await isScopeMismatchResponse(response))) {
+          if (oauth2Manager?.canRefresh()) {
+            reauthenticated = true;
+            await oauth2Manager.forceRefresh();
+            derivedAuthHeaders = await currentAuthHeaders();
+            continue;
+          }
+
+          if (getAuthOn401) {
+            reauthenticated = true;
+            derivedAuthHeaders = await getAuthHeaders(await getAuthOn401());
+            continue;
+          }
+        }
+
+        if (TRANSIENT_HTTP_STATUSES.has(response.status) && networkAttempt + 1 < retryMaxAttempts) {
+          networkAttempt += 1;
+          await new Promise(resolve => setTimeout(resolve, delayMs));
+          delayMs = Math.round(delayMs * retryBackoffFactor);
+          continue;
+        }
+
+        break;
+      }
+
+      if (!response.ok) {
+        const text = await response.text();
+        let detail: unknown = text;
+        try {
+          detail = JSON.parse(text);
+        } catch {
+          //
+        }
+        throw createApiError(
+          `Request failed: ${response.status} ${response.statusText}${text ? ` - ${text}` : ''}`,
+          response.status,
+          response.statusText,
+          detail,
+          response.headers,
+        );
+      }
+
+      const contentType = response.headers.get('content-type');
+
+      if (response.status === 204) return undefined as T;
+
+      // A download endpoint says so with `BufferSchema`, and it is the only
+      // reliable signal: the response carries the *file's* content type, so
+      // `text/plain` is as legitimate for a download as `application/pdf` and
+      // sniffing the header cannot tell the two intents apart. Without this the
+      // body was dropped on the floor and every download resolved to `undefined`.
+      if ((requestConfig.schema as unknown) === BufferSchema) {
+        return BufferSchema.parse(new Uint8Array(await response.arrayBuffer())) as T;
+      }
+
+      if (contentType && !contentType.includes('application/json')) {
+        // An endpoint that declares a schema and answers with something that is
+        // not JSON has broken its contract. Returning `undefined` here would
+        // hand back a value the caller's types say cannot occur, and the
+        // failure would surface far from the call that caused it.
+        if (requestConfig.schema) {
+          throw new SchemaMismatchError(
+            `Expected a JSON response to validate against the schema, got ${contentType}`,
+            await response.text(),
+          );
+        }
+
+        return undefined as T;
+      }
+
+      let data: unknown;
+
+      if (contentType?.includes('application/json')) {
+        const text = await response.text();
+
+        try {
+          data = JSON.parse(text);
+        } catch (e) {
+          if (e instanceof SyntaxError) {
+            // Confluence sometimes sends application/json Content-Type with a plain-text body
+            data = text || undefined;
+          } else {
+            throw e;
+          }
+        }
+      } else {
+        const text = await response.text();
+
+        data = text || undefined;
+      }
+
+      if (requestConfig.schema && data !== undefined) {
+        const parsed = requestConfig.schema.safeParse(data);
+
+        if (!parsed.success) {
+          // The response parsed as JSON but is not the shape the endpoint
+          // promises. Callers should not have to know zod is the validator to
+          // catch this, so it arrives as the library's own error with the
+          // validation issues preserved on `cause`.
+          throw new SchemaMismatchError(
+            `Response did not match the schema for ${requestConfig.method ?? 'GET'} ${requestConfig.url}`,
+            JSON.stringify(data),
+            { cause: parsed.error },
+          );
+        }
+
+        return parsed.data as T;
+      }
+
+      return data as T;
+    },
+  };
+}
diff --git a/src/core/errors/apiError.ts b/src/core/errors/apiError.ts
new file mode 100644
index 00000000..a9890f3e
--- /dev/null
+++ b/src/core/errors/apiError.ts
@@ -0,0 +1,168 @@
+import { ERROR_KINDS, hasErrorKind, type ErrorKind } from './kinds.js';
+
+export interface ApiErrorOptions {
+  /** The error that caused this one — a transport failure, a parse failure. */
+  cause?: unknown;
+}
+
+/**
+ * Thrown when Confluence returns a non-2xx HTTP response.
+ *
+ * The subclasses below cover the statuses worth branching on. Catch this one to catch them all, or a subclass — or use
+ * the predicates, which survive a duplicated install of this package.
+ *
+ * @stable
+ */
+export class ApiError extends Error {
+  readonly [ERROR_KINDS]: readonly ErrorKind[] = ['api'];
+
+  /** HTTP status. */
+  readonly status: number;
+  readonly statusText: string;
+  /** Atlassian's error payload, parsed when it was JSON and the raw text when it was not. */
+  readonly body: unknown;
+
+  constructor(message: string, status: number, statusText: string, body: unknown, options?: ApiErrorOptions) {
+    super(message, options);
+    this.name = 'ApiError';
+    this.status = status;
+    this.statusText = statusText;
+    this.body = body;
+    Object.setPrototypeOf(this, new.target.prototype);
+  }
+
+  static [Symbol.hasInstance](value: unknown): boolean {
+    return hasErrorKind(value, 'api');
+  }
+}
+
+/**
+ * 401 — the credentials are missing, expired or rejected.
+ *
+ * @stable
+ */
+export class AuthError extends ApiError {
+  override readonly [ERROR_KINDS]: readonly ErrorKind[] = ['api', 'auth'];
+
+  constructor(message: string, statusText: string, body: unknown, options?: ApiErrorOptions) {
+    super(message, 401, statusText, body, options);
+    this.name = 'AuthError';
+  }
+
+  static override [Symbol.hasInstance](value: unknown): boolean {
+    return hasErrorKind(value, 'auth');
+  }
+}
+
+/**
+ * 401 with `Unauthorized; scope does not match` — the token is valid, but the app never asked for a scope this endpoint
+ * needs.
+ *
+ * A subclass of {@link AuthError} because it is still a 401, but worth its own type: refreshing the token cannot fix
+ * it, so the client does not try. The app needs the scope added in the developer console and the user has to consent
+ * again.
+ *
+ * Under 3LO this is also how the two API versions bite: v2 endpoints want granular scopes (`read:page:confluence`),
+ * v1 endpoints want classic ones (`read:confluence-content.all`). An app that holds only one family gets this error
+ * from the other.
+ *
+ * @stable
+ */
+export class ScopeError extends AuthError {
+  override readonly [ERROR_KINDS]: readonly ErrorKind[] = ['api', 'auth', 'scope'];
+
+  constructor(message: string, statusText: string, body: unknown, options?: ApiErrorOptions) {
+    super(message, statusText, body, options);
+    this.name = 'ScopeError';
+  }
+
+  static override [Symbol.hasInstance](value: unknown): boolean {
+    return hasErrorKind(value, 'scope');
+  }
+}
+
+/**
+ * 403 — authenticated, but not allowed. Usually a Confluence permission rather than a scope.
+ *
+ * @stable
+ */
+export class ForbiddenError extends ApiError {
+  override readonly [ERROR_KINDS]: readonly ErrorKind[] = ['api', 'forbidden'];
+
+  constructor(message: string, statusText: string, body: unknown, options?: ApiErrorOptions) {
+    super(message, 403, statusText, body, options);
+    this.name = 'ForbiddenError';
+  }
+
+  static override [Symbol.hasInstance](value: unknown): boolean {
+    return hasErrorKind(value, 'forbidden');
+  }
+}
+
+/**
+ * 404 — no such thing, or no permission to know it exists.
+ *
+ * Confluence returns 404 for both, deliberately: telling the two apart would leak the existence of restricted content.
+ *
+ * @stable
+ */
+export class NotFoundError extends ApiError {
+  override readonly [ERROR_KINDS]: readonly ErrorKind[] = ['api', 'notFound'];
+
+  constructor(message: string, statusText: string, body: unknown, options?: ApiErrorOptions) {
+    super(message, 404, statusText, body, options);
+    this.name = 'NotFoundError';
+  }
+
+  static override [Symbol.hasInstance](value: unknown): boolean {
+    return hasErrorKind(value, 'notFound');
+  }
+}
+
+export interface RateLimitErrorOptions extends ApiErrorOptions {
+  /** How long to wait before retrying, in ms, when Confluence said so. */
+  retryAfterMs?: number;
+}
+
+/**
+ * 429 — you are being rate limited.
+ *
+ * `retryAfterMs` carries Atlassian's own advice when the response included `Retry-After`. It is not retried for you:
+ * the right response to a rate limit is to slow the whole client down, which only your code can decide.
+ *
+ * @stable
+ */
+export class RateLimitError extends ApiError {
+  override readonly [ERROR_KINDS]: readonly ErrorKind[] = ['api', 'rateLimit'];
+
+  /** Milliseconds to wait, from the `Retry-After` header. Undefined when the response did not say. */
+  readonly retryAfterMs?: number;
+
+  constructor(message: string, statusText: string, body: unknown, options?: RateLimitErrorOptions) {
+    super(message, 429, statusText, body, options);
+    this.name = 'RateLimitError';
+    this.retryAfterMs = options?.retryAfterMs;
+  }
+
+  static override [Symbol.hasInstance](value: unknown): boolean {
+    return hasErrorKind(value, 'rateLimit');
+  }
+}
+
+/**
+ * 5xx — Confluence failed on its own side.
+ *
+ * @stable
+ */
+export class ServerError extends ApiError {
+  override readonly [ERROR_KINDS]: readonly ErrorKind[] = ['api', 'server'];
+
+  constructor(message: string, status: number, statusText: string, body: unknown, options?: ApiErrorOptions) {
+    super(message, status, statusText, body, options);
+    this.name = 'ServerError';
+  }
+
+  static override [Symbol.hasInstance](value: unknown): boolean {
+    return hasErrorKind(value, 'server');
+  }
+}
diff --git a/src/core/errors/fromResponse.ts b/src/core/errors/fromResponse.ts
new file mode 100644
index 00000000..9f52e571
--- /dev/null
+++ b/src/core/errors/fromResponse.ts
@@ -0,0 +1,136 @@
+import {
+  ApiError,
+  AuthError,
+  ForbiddenError,
+  NotFoundError,
+  RateLimitError,
+  ScopeError,
+  ServerError,
+  type ApiErrorOptions,
+} from './apiError.js';
+import { NetworkError } from './networkError.js';
+import { PRODUCT } from '../productInfo.js';
+
+/** Node/undici error codes that signal a recoverable transport-layer failure. */
+const TRANSIENT_NETWORK_CODES = new Set([
+  'ECONNRESET',
+  'ECONNREFUSED',
+  'ETIMEDOUT',
+  'ENOTFOUND',
+  'EAI_AGAIN',
+  'EPIPE',
+  'UND_ERR_SOCKET',
+  'UND_ERR_CONNECT_TIMEOUT',
+  'UND_ERR_HEADERS_TIMEOUT',
+  'UND_ERR_BODY_TIMEOUT',
+]);
+
+/** HTTP statuses that signal a recoverable upstream failure. The single source of truth for both retry paths. */
+export const TRANSIENT_HTTP_STATUSES = new Set([502, 503, 504]);
+
+/**
+ * The transport-level error code, dug out of the `cause` chain.
+ *
+ * `fetch` reports a failed request as `TypeError: fetch failed` and hides the reason underneath, sometimes more than
+ * one level down, so the chain is walked rather than the top error inspected.
+ */
+function networkErrorCode(err: unknown): string | undefined {
+  let cursor: unknown = err;
+
+  for (let depth = 0; cursor instanceof Error && depth < 5; depth += 1) {
+    const code = (cursor as Error & { code?: string }).code;
+
+    if (code) return code;
+
+    cursor = (cursor as { cause?: unknown }).cause;
+  }
+
+  return undefined;
+}
+
+/** Whether a transport failure is worth retrying. Broken TLS sessions (`ERR_SSL_*`) count. */
+export function isTransientCode(code: string | undefined): boolean {
+  if (!code) return false;
+
+  return TRANSIENT_NETWORK_CODES.has(code) || code.startsWith('ERR_SSL_');
+}
+
+/** Wrap whatever `fetch` rejected with into a `NetworkError`, preserving the original as `cause`. */
+export function toNetworkError(err: unknown, url: string): NetworkError {
+  const code = networkErrorCode(err);
+  const reason = err instanceof Error ? err.message : String(err);
+
+  return new NetworkError(`Request to ${url} failed: ${reason}${code ? ` (${code})` : ''}`, {
+    cause: err,
+    code,
+    transient: isTransientCode(code),
+  });
+}
+
+/**
+ * `Retry-After` in milliseconds. The header is either delta-seconds or an HTTP date; both are accepted, and anything
+ * else is ignored rather than guessed at.
+ */
+export function parseRetryAfter(header: string | null, now = Date.now()): number | undefined {
+  if (!header) return undefined;
+
+  const seconds = Number(header);
+
+  if (Number.isFinite(seconds)) return Math.max(0, seconds * 1000);
+
+  const date = Date.parse(header);
+
+  if (Number.isNaN(date)) return undefined;
+
+  return Math.max(0, date - now);
+}
+
+/**
+ * Whether a 401 is really a missing scope.
+ *
+ * Confluence says so in the body — `{"code":401,"message":"Unauthorized; scope does not match"}` — and nowhere else,
+ * so the message is the only signal there is. Matched loosely, since the wording is Atlassian's to change; a miss
+ * only costs the caller a plain `AuthError`.
+ */
+function isScopeMismatch(body: unknown): boolean {
+  const message = typeof body === 'object' && body !== null ? (body as { message?: unknown }).message : body;
+
+  return typeof message === 'string' && /scope does not match/i.test(message);
+}
+
+/** Build the error class that matches the status, so callers can branch on the type instead of the number. */
+export function createApiError(
+  message: string,
+  status: number,
+  statusText: string,
+  body: unknown,
+  headers?: Headers,
+  options?: ApiErrorOptions,
+): ApiError {
+  if (status === 401) {
+    return isScopeMismatch(body)
+      ? new ScopeError(
+        `${message}\n\nThe token is missing a scope this endpoint requires. Refreshing will not help: add the ` +
+            `scope in the developer console and have the user authorize again.${PRODUCT.scopeHint ? ` ${PRODUCT.scopeHint}` : ''}`,
+        statusText,
+        body,
+        options,
+      )
+      : new AuthError(message, statusText, body, options);
+  }
+
+  if (status === 403) return new ForbiddenError(message, statusText, body, options);
+
+  if (status === 404) return new NotFoundError(message, statusText, body, options);
+
+  if (status === 429) {
+    return new RateLimitError(message, statusText, body, {
+      ...options,
+      retryAfterMs: parseRetryAfter(headers?.get('retry-after') ?? null),
+    });
+  }
+
+  if (status >= 500) return new ServerError(message, status, statusText, body, options);
+
+  return new ApiError(message, status, statusText, body, options);
+}
diff --git a/src/core/errors/index.ts b/src/core/errors/index.ts
new file mode 100644
index 00000000..16f611e6
--- /dev/null
+++ b/src/core/errors/index.ts
@@ -0,0 +1,42 @@
+export {
+  ApiError,
+  AuthError,
+  ForbiddenError,
+  NotFoundError,
+  RateLimitError,
+  ScopeError,
+  ServerError,
+  type ApiErrorOptions,
+  type RateLimitErrorOptions,
+} from './apiError.js';
+
+export { NetworkError } from './networkError.js';
+
+export { OAuthError, ConfigError, type OAuthErrorOptions } from './oauthError.js';
+
+export { SchemaMismatchError } from './schemaMismatchError.js';
+
+export {
+  isApiError,
+  isAuthError,
+  isForbiddenError,
+  isNotFoundError,
+  isRateLimitError,
+  isServerError,
+  isNetworkError,
+  isOAuthError,
+  isConfigError,
+  isSchemaMismatchError,
+  isReauthorizationRequired,
+  isScopeError,
+} from './predicates.js';
+
+export {
+  createApiError,
+  toNetworkError,
+  parseRetryAfter,
+  isTransientCode,
+  TRANSIENT_HTTP_STATUSES,
+} from './fromResponse.js';
+
+export { ERROR_KINDS, hasErrorKind, type ErrorKind } from './kinds.js';
diff --git a/src/core/errors/kinds.ts b/src/core/errors/kinds.ts
new file mode 100644
index 00000000..647674f5
--- /dev/null
+++ b/src/core/errors/kinds.ts
@@ -0,0 +1,33 @@
+import { PRODUCT } from '../productInfo.js';
+
+/**
+ * Every error this package throws carries the list of kinds it belongs to, under a well-known symbol.
+ *
+ * The predicates read that list rather than the prototype chain, so they keep working when two copies of the package
+ * end up in one process — a realistic outcome of transitive dependency ranges, and one where `instanceof` silently
+ * returns false. `instanceof` still works, because each class also implements `Symbol.hasInstance` on top of the same
+ * list.
+ */
+export const ERROR_KINDS = Symbol.for(`${PRODUCT.packageName}:error-kinds`);
+
+export type ErrorKind =
+  | 'api'
+  | 'auth'
+  | 'forbidden'
+  | 'notFound'
+  | 'rateLimit'
+  | 'server'
+  | 'network'
+  | 'oauth'
+  | 'config'
+  | 'schemaMismatch'
+  | 'scope';
+
+/** Whether `value` is one of this package's errors of the given kind. */
+export function hasErrorKind(value: unknown, kind: ErrorKind): boolean {
+  if (typeof value !== 'object' || value === null) return false;
+
+  const kinds = (value as Record)[ERROR_KINDS];
+
+  return Array.isArray(kinds) && kinds.includes(kind);
+}
diff --git a/src/core/errors/networkError.ts b/src/core/errors/networkError.ts
new file mode 100644
index 00000000..8824f2bd
--- /dev/null
+++ b/src/core/errors/networkError.ts
@@ -0,0 +1,30 @@
+import { ERROR_KINDS, hasErrorKind, type ErrorKind } from './kinds.js';
+
+/**
+ * The request never produced an HTTP response — DNS, TLS, a reset socket, a timeout, an unreachable host.
+ *
+ * `fetch` reports these as a bare `TypeError` whose real reason is buried in `cause`. Wrapping them means a caller can
+ * catch every failure of this client uniformly, and `transient` says whether retrying stands a chance.
+ *
+ * @stable
+ */
+export class NetworkError extends Error {
+  readonly [ERROR_KINDS]: readonly ErrorKind[] = ['network'];
+
+  /** The underlying error code, e.g. `ECONNRESET`, when one was found. */
+  readonly code?: string;
+  /** Whether the failure looks retryable rather than permanent. */
+  readonly transient: boolean;
+
+  constructor(message: string, options: { cause: unknown; code?: string; transient: boolean }) {
+    super(message, { cause: options.cause });
+    this.name = 'NetworkError';
+    this.code = options.code;
+    this.transient = options.transient;
+    Object.setPrototypeOf(this, new.target.prototype);
+  }
+
+  static [Symbol.hasInstance](value: unknown): boolean {
+    return hasErrorKind(value, 'network');
+  }
+}
diff --git a/src/core/errors/oauthError.ts b/src/core/errors/oauthError.ts
new file mode 100644
index 00000000..9bd2b809
--- /dev/null
+++ b/src/core/errors/oauthError.ts
@@ -0,0 +1,103 @@
+import { ERROR_KINDS, hasErrorKind, type ErrorKind } from './kinds.js';
+
+export interface OAuthErrorOptions {
+  cause?: unknown;
+  /** HTTP status, when the failure came from Atlassian's auth endpoints rather than from your configuration. */
+  status?: number;
+  /** The auth server's response body, parsed when it was JSON. */
+  body?: unknown;
+  /** The OAuth 2.0 error code, e.g. `invalid_grant`. */
+  error?: string;
+  /** The auth server's human-readable explanation. */
+  errorDescription?: string;
+  /**
+   * Whether the grant is unrecoverable and the user has to authorize again.
+   *
+   * Set explicitly where the code alone cannot say. Atlassian answers `access_denied` both when the user declines the
+   * consent screen — re-authorizing is exactly right — and when the client secret is wrong, where re-authorizing would
+   * loop the user forever over what is really a deployment mistake.
+   */
+  reauthorizationRequired?: boolean;
+}
+
+/** The OAuth 2.0 `{ error, error_description }` pair, when the body carried one. */
+function readErrorFields(body: unknown): { error?: string; errorDescription?: string } {
+  if (typeof body !== 'object' || body === null) return {};
+
+  const { error, error_description: description } = body as { error?: unknown; error_description?: unknown };
+
+  return {
+    error: typeof error === 'string' ? error : undefined,
+    errorDescription: typeof description === 'string' ? description : undefined,
+  };
+}
+
+/**
+ * An OAuth 2.0 failure: the token endpoint rejected the request, or the client cannot proceed with what it was given.
+ *
+ * Deliberately not an `ApiError`: it does not come from the Confluence API, and a caller retrying Confluence calls
+ * should not treat "your refresh token is dead" as the same class of problem as "that page is missing".
+ *
+ * @stable
+ */
+export class OAuthError extends Error {
+  readonly [ERROR_KINDS]: readonly ErrorKind[] = ['oauth'];
+
+  readonly status?: number;
+  readonly body?: unknown;
+  /**
+   * The OAuth 2.0 error code from the auth server, e.g. `invalid_grant` or `access_denied`.
+   *
+   * Branch on this rather than on `status`: the code names what went wrong, while the status Atlassian pairs it with is
+   * an implementation detail that has changed before.
+   */
+  readonly error?: string;
+  readonly errorDescription?: string;
+  /** Whether the only way forward is a fresh authorization. Read it through {@link isReauthorizationRequired}. */
+  readonly reauthorizationRequired: boolean;
+
+  constructor(message: string, options?: OAuthErrorOptions) {
+    super(message, { cause: options?.cause });
+
+    const fromBody = readErrorFields(options?.body);
+
+    this.name = 'OAuthError';
+    this.status = options?.status;
+    this.body = options?.body;
+    this.error = options?.error ?? fromBody.error;
+    this.errorDescription = options?.errorDescription ?? fromBody.errorDescription;
+    // `invalid_grant` is what Atlassian documents for a rotated-out or expired
+    // token; `unauthorized_client` is what it actually sends when the refresh
+    // token is unknown. Both mean the stored grant is dead. `access_denied` is
+    // deliberately absent — from the token endpoint it means a bad client secret.
+    this.reauthorizationRequired =
+      options?.reauthorizationRequired ?? (this.error === 'invalid_grant' || this.error === 'unauthorized_client');
+    Object.setPrototypeOf(this, new.target.prototype);
+  }
+
+  static [Symbol.hasInstance](value: unknown): boolean {
+    return hasErrorKind(value, 'oauth');
+  }
+}
+
+/**
+ * The client was configured in a way that cannot work — contradictory options, or a required one missing.
+ *
+ * Thrown at construction time where possible, so a mistake surfaces before the first request rather than as a puzzling
+ * 401.
+ *
+ * @stable
+ */
+export class ConfigError extends Error {
+  readonly [ERROR_KINDS]: readonly ErrorKind[] = ['config'];
+
+  constructor(message: string, options?: { cause?: unknown }) {
+    super(message, options);
+    this.name = 'ConfigError';
+    Object.setPrototypeOf(this, new.target.prototype);
+  }
+
+  static [Symbol.hasInstance](value: unknown): boolean {
+    return hasErrorKind(value, 'config');
+  }
+}
diff --git a/src/core/errors/predicates.ts b/src/core/errors/predicates.ts
new file mode 100644
index 00000000..b351b100
--- /dev/null
+++ b/src/core/errors/predicates.ts
@@ -0,0 +1,134 @@
+import type {
+  ApiError,
+  AuthError,
+  ForbiddenError,
+  NotFoundError,
+  RateLimitError,
+  ScopeError,
+  ServerError,
+} from './apiError.js';
+import type { ConfigError, OAuthError } from './oauthError.js';
+import type { NetworkError } from './networkError.js';
+import type { SchemaMismatchError } from './schemaMismatchError.js';
+import { hasErrorKind } from './kinds.js';
+
+/**
+ * Any non-2xx response from Confluence, including every subclass.
+ *
+ * Prefer these predicates to `instanceof` in library code and in anything that might load two copies of this package:
+ * they check a branded marker instead of the prototype chain.
+ *
+ * @stable
+ */
+export function isApiError(value: unknown): value is ApiError {
+  return hasErrorKind(value, 'api');
+}
+
+/**
+ * 401 — credentials missing, expired or rejected.
+ *
+ * @stable
+ */
+export function isAuthError(value: unknown): value is AuthError {
+  return hasErrorKind(value, 'auth');
+}
+
+/**
+ * 403 — authenticated but not permitted.
+ *
+ * @stable
+ */
+export function isForbiddenError(value: unknown): value is ForbiddenError {
+  return hasErrorKind(value, 'forbidden');
+}
+
+/**
+ * 404 — absent, or invisible to you.
+ *
+ * @stable
+ */
+export function isNotFoundError(value: unknown): value is NotFoundError {
+  return hasErrorKind(value, 'notFound');
+}
+
+/**
+ * 429 — rate limited. Read `retryAfterMs` for Atlassian's own advice.
+ *
+ * @stable
+ */
+export function isRateLimitError(value: unknown): value is RateLimitError {
+  return hasErrorKind(value, 'rateLimit');
+}
+
+/**
+ * 5xx — Confluence failed on its side.
+ *
+ * @stable
+ */
+export function isServerError(value: unknown): value is ServerError {
+  return hasErrorKind(value, 'server');
+}
+
+/**
+ * No HTTP response at all — DNS, TLS, socket, timeout.
+ *
+ * @stable
+ */
+export function isNetworkError(value: unknown): value is NetworkError {
+  return hasErrorKind(value, 'network');
+}
+
+/**
+ * An OAuth 2.0 failure: token exchange, refresh, or cloud-id resolution.
+ *
+ * @stable
+ */
+export function isOAuthError(value: unknown): value is OAuthError {
+  return hasErrorKind(value, 'oauth');
+}
+
+/**
+ * The client configuration cannot work.
+ *
+ * @stable
+ */
+export function isConfigError(value: unknown): value is ConfigError {
+  return hasErrorKind(value, 'config');
+}
+
+/**
+ * A 2xx response that is not JSON where the endpoint promised JSON.
+ *
+ * @stable
+ */
+export function isSchemaMismatchError(value: unknown): value is SchemaMismatchError {
+  return hasErrorKind(value, 'schemaMismatch');
+}
+
+/**
+ * The grant is gone: no refresh will fix it, and the user has to authorize again.
+ *
+ * Covers a refresh token that expired after 90 days idle, one rotated out because the new one was never persisted, a
+ * user who changed their Atlassian password, and a user who declined the consent screen.
+ *
+ * Deliberately narrower than "any OAuth failure". A wrong client secret also fails the token endpoint — with
+ * `access_denied`, the same code a declining user produces — and sending people through consent over a bad environment
+ * variable would loop them forever. That case answers `false` here and surfaces as a plain {@link isOAuthError}.
+ *
+ * @stable
+ */
+export function isReauthorizationRequired(value: unknown): value is OAuthError {
+  return isOAuthError(value) && value.reauthorizationRequired;
+}
+
+/**
+ * The token is valid but lacks a scope this endpoint requires.
+ *
+ * Distinct from {@link isAuthError} because the remedy is different: refreshing cannot help, the app needs the scope
+ * added and the user has to consent again. Confluence reports it as a 401 with `Unauthorized; scope does not match`.
+ *
+ * @stable
+ */
+export function isScopeError(value: unknown): value is ScopeError {
+  return hasErrorKind(value, 'scope');
+}
diff --git a/src/core/errors/schemaMismatchError.ts b/src/core/errors/schemaMismatchError.ts
new file mode 100644
index 00000000..d457606a
--- /dev/null
+++ b/src/core/errors/schemaMismatchError.ts
@@ -0,0 +1,33 @@
+import { ERROR_KINDS, hasErrorKind, type ErrorKind } from './kinds.js';
+
+/**
+ * The request succeeded, but the response is not what the endpoint's schema describes.
+ *
+ * Covers both ways that can happen: the response was not JSON at all, or it parsed as JSON and its shape had drifted.
+ * The two are told apart by `cause` — a validation failure carries the underlying `ZodError`, a non-JSON response
+ * carries nothing — while `body` holds what actually arrived either way.
+ *
+ * They are one error rather than two on purpose: from a caller's side both mean "the API answered 2xx and the value
+ * cannot be trusted", and nobody should have to know which validator this library uses in order to catch that.
+ *
+ * Distinct from `ApiError`, which means the request itself failed.
+ *
+ * @stable
+ */
+export class SchemaMismatchError extends Error {
+  readonly [ERROR_KINDS]: readonly ErrorKind[] = ['schemaMismatch'];
+
+  /** The raw response body, so you can see what arrived instead. */
+  readonly body: string;
+
+  constructor(message: string, body: string, options?: { cause?: unknown }) {
+    super(message, options);
+    this.name = 'SchemaMismatchError';
+    this.body = body;
+    Object.setPrototypeOf(this, new.target.prototype);
+  }
+
+  static [Symbol.hasInstance](value: unknown): boolean {
+    return hasErrorKind(value, 'schemaMismatch');
+  }
+}
diff --git a/src/core/formData/attachmentInput.ts b/src/core/formData/attachmentInput.ts
new file mode 100644
index 00000000..4869be52
--- /dev/null
+++ b/src/core/formData/attachmentInput.ts
@@ -0,0 +1,19 @@
+/**
+ * Anything you can hand to an attachment endpoint as file content.
+ *
+ * Deliberately spelled with web types only, so the declaration compiles in a browser project that has no `@types/node`.
+ * Nothing is lost by it: Node's `Buffer` extends `Uint8Array`, and a `Readable` stream is structurally an
+ * `AsyncIterable`, so both still fit — they just are not named here.
+ */
+export type AttachmentContent =
+  | File
+  | Blob
+  | Uint8Array
+  | ReadableStream
+  | AsyncIterable
+  | string;
+
+export type AttachmentInput = {
+  filename: string;
+  content: AttachmentContent;
+};
diff --git a/src/core/formData/bufferSchema.ts b/src/core/formData/bufferSchema.ts
new file mode 100644
index 00000000..7a1867c3
--- /dev/null
+++ b/src/core/formData/bufferSchema.ts
@@ -0,0 +1,11 @@
+import { z } from 'zod';
+
+export const BufferSchema = z.custom(val => {
+  if (val instanceof ArrayBuffer) return true;
+
+  if (typeof ArrayBuffer !== 'undefined' && ArrayBuffer.isView(val)) return true;
+
+  return false;
+});
+
+export type Buffer = z.infer;
diff --git a/src/core/formData/index.ts b/src/core/formData/index.ts
new file mode 100644
index 00000000..829607fa
--- /dev/null
+++ b/src/core/formData/index.ts
@@ -0,0 +1,7 @@
+export type { AttachmentContent, AttachmentInput } from './attachmentInput.js';
+
+export { BufferSchema, type Buffer } from './bufferSchema.js';
+
+export { createMultipartRequestBody, toFormDataFile, type MultipartRequestBody } from './multipartRequest.js';
+
+export { mimeTypeFor, DEFAULT_MIME_TYPE } from './mimeType.js';
diff --git a/src/core/formData/mimeType.ts b/src/core/formData/mimeType.ts
new file mode 100644
index 00000000..2c46c668
--- /dev/null
+++ b/src/core/formData/mimeType.ts
@@ -0,0 +1,89 @@
+/**
+ * Content type for an attachment, guessed from its filename.
+ *
+ * Atlassian stores whatever content type the upload declares, and it decides whether a browser previews the file or
+ * offers it as a download. Sending `application/octet-stream` for everything turns every screenshot into an anonymous
+ * blob, which is why this exists.
+ *
+ * The table is deliberately short: the formats people actually attach to issues and pages. A full database is a
+ * megabyte of dependency for a lookup that misses nothing anyone will notice — an unknown extension simply falls back
+ * to `application/octet-stream`, which is what the upload would have said anyway.
+ */
+const MIME_TYPES: Record = {
+  // Images
+  png: 'image/png',
+  jpg: 'image/jpeg',
+  jpeg: 'image/jpeg',
+  gif: 'image/gif',
+  webp: 'image/webp',
+  svg: 'image/svg+xml',
+  bmp: 'image/bmp',
+  ico: 'image/vnd.microsoft.icon',
+  tif: 'image/tiff',
+  tiff: 'image/tiff',
+  avif: 'image/avif',
+  heic: 'image/heic',
+
+  // Documents
+  pdf: 'application/pdf',
+  doc: 'application/msword',
+  docx: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
+  xls: 'application/vnd.ms-excel',
+  xlsx: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
+  ppt: 'application/vnd.ms-powerpoint',
+  pptx: 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
+  odt: 'application/vnd.oasis.opendocument.text',
+  ods: 'application/vnd.oasis.opendocument.spreadsheet',
+  rtf: 'application/rtf',
+
+  // Text and data
+  txt: 'text/plain',
+  md: 'text/markdown',
+  csv: 'text/csv',
+  tsv: 'text/tab-separated-values',
+  log: 'text/plain',
+  json: 'application/json',
+  xml: 'application/xml',
+  yaml: 'application/yaml',
+  yml: 'application/yaml',
+  html: 'text/html',
+  htm: 'text/html',
+  css: 'text/css',
+  js: 'text/javascript',
+  mjs: 'text/javascript',
+  ts: 'text/plain',
+  sql: 'application/sql',
+
+  // Archives
+  zip: 'application/zip',
+  gz: 'application/gzip',
+  tar: 'application/x-tar',
+  '7z': 'application/x-7z-compressed',
+  rar: 'application/vnd.rar',
+  bz2: 'application/x-bzip2',
+
+  // Media
+  mp4: 'video/mp4',
+  webm: 'video/webm',
+  mov: 'video/quicktime',
+  avi: 'video/x-msvideo',
+  mp3: 'audio/mpeg',
+  wav: 'audio/wav',
+  ogg: 'audio/ogg',
+  m4a: 'audio/mp4',
+};
+
+export const DEFAULT_MIME_TYPE = 'application/octet-stream';
+
+/**
+ * The content type for `filename`, or `application/octet-stream` when the extension is unknown or absent.
+ *
+ * A leading dot is not an extension — `.gitignore` is a file called `.gitignore`, not a `gitignore` file.
+ */
+export function mimeTypeFor(filename: string): string {
+  const lastDot = filename.lastIndexOf('.');
+
+  if (lastDot <= 0) return DEFAULT_MIME_TYPE;
+
+  return MIME_TYPES[filename.slice(lastDot + 1).toLowerCase()] ?? DEFAULT_MIME_TYPE;
+}
diff --git a/src/core/formData/multipartRequest.ts b/src/core/formData/multipartRequest.ts
new file mode 100644
index 00000000..81e1b630
--- /dev/null
+++ b/src/core/formData/multipartRequest.ts
@@ -0,0 +1,258 @@
+import type { AttachmentInput, AttachmentContent } from './attachmentInput.js';
+import { mimeTypeFor } from './mimeType.js';
+import { PRODUCT_SLUG } from '../productInfo.js';
+
+export type MultipartRequestBody = {
+  body: FormData | ReadableStream;
+  headers?: Record;
+};
+
+const textEncoder = new TextEncoder();
+
+let streamingSupport: boolean | undefined;
+
+/**
+ * Whether this runtime accepts a `ReadableStream` as a request body.
+ *
+ * Node and Chromium do and signal it by reading `duplex`; Firefox and Safari do not, and the option stays untouched.
+ * Detecting it this way rather than by sniffing for `process` matters: bundlers routinely shim `process` as an empty
+ * object, where reading `process.versions.node` throws outright.
+ *
+ * The probe constructs a request and discards it, so the caller's own stream is never touched.
+ */
+function supportsRequestStreaming(): boolean {
+  if (streamingSupport !== undefined) return streamingSupport;
+
+  if (typeof Request === 'undefined' || typeof ReadableStream === 'undefined') {
+    streamingSupport = false;
+
+    return streamingSupport;
+  }
+
+  let duplexRead = false;
+
+  try {
+    new Request('https://streaming.probe.invalid', {
+      method: 'POST',
+      body: new ReadableStream(),
+      get duplex() {
+        duplexRead = true;
+
+        return 'half';
+      },
+    } as RequestInit);
+  } catch {
+    // A runtime that refuses a stream body outright cannot stream either.
+    duplexRead = false;
+  }
+
+  streamingSupport = duplexRead;
+
+  return streamingSupport;
+}
+
+function isAsyncIterable(value: unknown): value is AsyncIterable {
+  if (value == null) return false;
+
+  return typeof (value as { [Symbol.asyncIterator]?: unknown })[Symbol.asyncIterator] === 'function';
+}
+
+/** Node's `Buffer` is a `Uint8Array`, so the structural check covers it without naming a Node type. */
+function isBytes(value: unknown): value is Uint8Array {
+  return ArrayBuffer.isView(value) && !(value instanceof DataView);
+}
+
+function isStreamLikeContent(content: AttachmentContent): boolean {
+  if (typeof content === 'string') return false;
+
+  if (content instanceof Blob) return false;
+
+  if (isBytes(content)) return false;
+
+  if (typeof ReadableStream !== 'undefined' && content instanceof ReadableStream) return true;
+
+  return isAsyncIterable(content);
+}
+
+function escapeQuotes(value: string): string {
+  return value.replace(/"/g, '%22');
+}
+
+function normalizeChunk(chunk: Uint8Array | string): Uint8Array {
+  if (typeof chunk === 'string') {
+    return textEncoder.encode(chunk);
+  }
+
+  return chunk;
+}
+
+async function* readableStreamToAsyncIterable(stream: ReadableStream): AsyncIterable {
+  const reader = stream.getReader();
+  try {
+    for (;;) {
+      const { value, done } = await reader.read();
+
+      if (done) return;
+
+      yield normalizeChunk(value);
+    }
+  } finally {
+    reader.releaseLock();
+  }
+}
+
+async function* contentToAsyncIterable(content: AttachmentContent): AsyncIterable {
+  if (typeof content === 'string') {
+    yield textEncoder.encode(content);
+
+    return;
+  }
+
+  if (content instanceof Blob) {
+    for await (const chunk of readableStreamToAsyncIterable(content.stream() as ReadableStream)) {
+      yield chunk;
+    }
+
+    return;
+  }
+
+  if (isBytes(content)) {
+    yield content;
+
+    return;
+  }
+
+  if (typeof ReadableStream !== 'undefined' && content instanceof ReadableStream) {
+    for await (const chunk of readableStreamToAsyncIterable(content as ReadableStream)) {
+      yield chunk;
+    }
+
+    return;
+  }
+
+  if (isAsyncIterable(content)) {
+    for await (const chunk of content) {
+      yield normalizeChunk(chunk);
+    }
+
+    return;
+  }
+
+  throw new TypeError('Unsupported attachment content type');
+}
+
+function createBoundary(): string {
+  const suffix =
+    typeof crypto !== 'undefined' && 'randomUUID' in crypto
+      ? crypto.randomUUID().replace(/-/g, '')
+      : `${Date.now()}${Math.random().toString(16).slice(2)}`;
+
+  return `${PRODUCT_SLUG}-${suffix}`;
+}
+
+function toReadableStream(iterable: AsyncIterable): ReadableStream {
+  const iterator = iterable[Symbol.asyncIterator]();
+
+  return new ReadableStream({
+    async pull(controller) {
+      const { value, done } = await iterator.next();
+
+      if (done) {
+        controller.close();
+
+        return;
+      }
+
+      controller.enqueue(value);
+    },
+    async cancel() {
+      if (typeof iterator.return === 'function') {
+        await iterator.return();
+      }
+    },
+  });
+}
+
+async function* encodeMultipart(attachments: AttachmentInput[], boundary: string): AsyncIterable {
+  for (const attachment of attachments) {
+    // A Blob knows its own type; otherwise the filename is what we have.
+    const contentType =
+      attachment.content instanceof Blob && attachment.content.type
+        ? attachment.content.type
+        : mimeTypeFor(attachment.filename);
+
+    const preamble = `--${boundary}\r\nContent-Disposition: form-data; name="file"; filename="${escapeQuotes(attachment.filename)}"\r\nContent-Type: ${contentType}\r\n\r\n`;
+    yield textEncoder.encode(preamble);
+
+    for await (const chunk of contentToAsyncIterable(attachment.content)) {
+      yield chunk;
+    }
+
+    yield textEncoder.encode('\r\n');
+  }
+
+  yield textEncoder.encode(`--${boundary}--\r\n`);
+}
+
+/**
+ * One {@link AttachmentInput} as a single `FormData`-appendable part.
+ *
+ * Multipart endpoints assemble their own `FormData` and append each attachment to it, so they need the content as one
+ * value rather than as a whole encoded body — that is what this provides, and {@link createMultipartRequestBody} is the
+ * streaming alternative for callers building a request by hand.
+ *
+ * Streaming content is collected here: a `FormData` part has to know its length, so a stream cannot stay lazy once it
+ * goes into one.
+ */
+export async function toFormDataFile(attachment: AttachmentInput): Promise {
+  const { content } = attachment;
+
+  if (content instanceof Blob) return content;
+
+  // The filename is the only clue to the content type, and Atlassian decides
+  // whether to preview or download based on what we send.
+  const type = mimeTypeFor(attachment.filename);
+  const chunks: Uint8Array[] = [];
+
+  for await (const chunk of contentToAsyncIterable(content)) chunks.push(chunk);
+
+  return new Blob(chunks as BlobPart[], { type });
+}
+
+/**
+ * A multipart body for `input`, streaming it where the runtime allows.
+ *
+ * Content that is already in memory — a `File`, `Blob`, `Uint8Array` or string — goes into a `FormData`, which every
+ * runtime handles and which lets the platform read a `File` off disk without loading it.
+ *
+ * Streaming content is sent as a stream where request streaming exists (Node, Chromium over HTTP/2) and is otherwise
+ * collected into a `Blob` first, because Firefox and Safari cannot send a stream at all. Collecting is the fallback
+ * rather than the default, so nothing silently buffers a large upload on a runtime that could have streamed it.
+ */
+export async function createMultipartRequestBody(
+  input: AttachmentInput | AttachmentInput[],
+): Promise {
+  const attachments = Array.isArray(input) ? input : [input];
+  const hasStreamingInput = attachments.some(attachment => isStreamLikeContent(attachment.content));
+
+  if (hasStreamingInput && supportsRequestStreaming()) {
+    const boundary = createBoundary();
+
+    return {
+      body: toReadableStream(encodeMultipart(attachments, boundary)),
+      headers: {
+        'Content-Type': `multipart/form-data; boundary=${boundary}`,
+      },
+    };
+  }
+
+  const formData = new FormData();
+
+  for (const attachment of attachments) {
+    // Collapses a stream into a Blob when we got here by falling back; a no-op
+    // for content that was already in memory.
+    formData.append('file', await toFormDataFile(attachment), attachment.filename);
+  }
+
+  return { body: formData };
+}
diff --git a/src/core/index.ts b/src/core/index.ts
new file mode 100644
index 00000000..66ab563e
--- /dev/null
+++ b/src/core/index.ts
@@ -0,0 +1,78 @@
+export {
+  ApiError,
+  AuthError,
+  ForbiddenError,
+  NotFoundError,
+  RateLimitError,
+  ScopeError,
+  ServerError,
+  NetworkError,
+  OAuthError,
+  ConfigError,
+  SchemaMismatchError,
+  isApiError,
+  isAuthError,
+  isForbiddenError,
+  isNotFoundError,
+  isRateLimitError,
+  isServerError,
+  isNetworkError,
+  isOAuthError,
+  isConfigError,
+  isSchemaMismatchError,
+  isReauthorizationRequired,
+  isScopeError,
+  type ApiErrorOptions,
+  type RateLimitErrorOptions,
+  type OAuthErrorOptions,
+} from './errors/index.js';
+
+export { apiObject } from './apiObject.js';
+
+export { createClient } from './createClient.js';
+
+export type { Client } from './interfaces/index.js';
+
+
+export {
+  httpMethodSchema,
+  clientConfigSchema,
+  authSchema,
+  authOAuth2Schema,
+  sendRequestOptionsSchema,
+  type HttpMethod,
+  type ClientConfig,
+  type Auth,
+  type AuthBasic,
+  type AuthBearer,
+  type AuthOAuth2,
+  type SendRequestOptions,
+} from './schemas/index.js';
+
+export {
+  generateAuthorizationUrl,
+  exchangeAuthorizationCode,
+  refreshOAuth2Token,
+  getAccessibleResources,
+  parseCallbackUrl,
+  createOAuth2Manager,
+} from './oauth/index.js';
+
+export type {
+  CallbackParams,
+  ParseCallbackUrlOptions,
+  OAuth2Manager,
+  OAuth2ManagerOptions,
+  OAuth2TokenResponse,
+  AccessibleResource,
+  TokenRefreshEvent,
+  OnTokenRefresh,
+} from './oauth/index.js';
+
+export { BufferSchema, createMultipartRequestBody, toFormDataFile, mimeTypeFor } from './formData/index.js';
+
+export type { AttachmentContent, AttachmentInput, Buffer, MultipartRequestBody } from './formData/index.js';
+
+export { withRetry } from './withRetry.js';
+
+export type { RetryOptions } from './withRetry.js';
diff --git a/src/core/interfaces/client.ts b/src/core/interfaces/client.ts
new file mode 100644
index 00000000..7b32625f
--- /dev/null
+++ b/src/core/interfaces/client.ts
@@ -0,0 +1,5 @@
+import type { SendRequestOptions } from '../schemas/index.js';
+
+export interface Client {
+  sendRequest(options: SendRequestOptions): Promise;
+}
diff --git a/src/core/interfaces/index.ts b/src/core/interfaces/index.ts
new file mode 100644
index 00000000..8441b9d0
--- /dev/null
+++ b/src/core/interfaces/index.ts
@@ -0,0 +1 @@
+export type { Client } from './client.js';
diff --git a/src/core/oauth/helpers.ts b/src/core/oauth/helpers.ts
new file mode 100644
index 00000000..0683d9b1
--- /dev/null
+++ b/src/core/oauth/helpers.ts
@@ -0,0 +1,148 @@
+import type { AccessibleResource, OAuth2TokenResponse } from './types.js';
+import { OAuthError } from '../errors/index.js';
+
+const AUTHORIZE_URL = 'https://auth.atlassian.com/authorize';
+const TOKEN_URL = 'https://auth.atlassian.com/oauth/token';
+const ACCESSIBLE_RESOURCES_URL = 'https://api.atlassian.com/oauth/token/accessible-resources';
+const DEFAULT_AUDIENCE = 'api.atlassian.com';
+const JSON_HEADERS = { 'Content-Type': 'application/json', Accept: 'application/json' };
+
+interface RawTokenResponse {
+  access_token: string;
+  refresh_token?: string;
+  expires_in: number;
+  scope: string;
+  token_type: string;
+}
+
+function mapTokenResponse(data: RawTokenResponse): OAuth2TokenResponse {
+  return {
+    accessToken: data.access_token,
+    refreshToken: data.refresh_token,
+    expiresIn: data.expires_in,
+    scope: data.scope,
+    tokenType: data.token_type,
+  };
+}
+
+/** `fetch` does not reject on a non-2xx status, so the status is checked here and turned into an `OAuthError`. */
+async function requestJson(url: string, init: RequestInit): Promise {
+  let response: Response;
+
+  try {
+    response = await fetch(url, init);
+  } catch (err) {
+    throw new OAuthError(`Request to ${url} failed before a response arrived`, { cause: err });
+  }
+
+  if (!response.ok) {
+    const text = await response.text().catch(() => '');
+    let body: unknown = text;
+
+    try {
+      body = JSON.parse(text);
+    } catch {
+      //
+    }
+
+    throw new OAuthError(
+      `Request to ${url} failed with status ${response.status} ${response.statusText}${text ? `: ${text}` : ''}`,
+      { status: response.status, body },
+    );
+  }
+
+  return response.json() as Promise;
+}
+
+/**
+ * Build the URL to send the user to so they can grant access.
+ *
+ * `state` is yours to generate and to verify when the callback comes back — it is what stops CSRF on the redirect.
+ *
+ * @stable
+ */
+export function generateAuthorizationUrl(params: {
+  clientId: string;
+  scopes: string[];
+  redirectUri: string;
+  state: string;
+  prompt?: string;
+  audience?: string;
+}): string {
+  const query = new URLSearchParams({
+    audience: params.audience ?? DEFAULT_AUDIENCE,
+    client_id: params.clientId,
+    scope: params.scopes.join(' '),
+    redirect_uri: params.redirectUri,
+    state: params.state,
+    response_type: 'code',
+    prompt: params.prompt ?? 'consent',
+  });
+
+  return `${AUTHORIZE_URL}?${query.toString()}`;
+}
+
+/**
+ * Exchange the authorization `code` from the redirect callback for tokens.
+ *
+ * @stable
+ */
+export async function exchangeAuthorizationCode(params: {
+  clientId: string;
+  clientSecret: string;
+  code: string;
+  redirectUri: string;
+}): Promise {
+  const data = await requestJson(TOKEN_URL, {
+    method: 'POST',
+    headers: JSON_HEADERS,
+    body: JSON.stringify({
+      grant_type: 'authorization_code',
+      client_id: params.clientId,
+      client_secret: params.clientSecret,
+      code: params.code,
+      redirect_uri: params.redirectUri,
+    }),
+  });
+
+  return mapTokenResponse(data);
+}
+
+/**
+ * Refresh an access token.
+ *
+ * Atlassian rotates the refresh token on every call: persist the one you get back and drop the old one, or the next
+ * refresh fails.
+ *
+ * @stable
+ */
+export async function refreshOAuth2Token(params: {
+  clientId: string;
+  clientSecret: string;
+  refreshToken: string;
+}): Promise {
+  const data = await requestJson(TOKEN_URL, {
+    method: 'POST',
+    headers: JSON_HEADERS,
+    body: JSON.stringify({
+      grant_type: 'refresh_token',
+      client_id: params.clientId,
+      client_secret: params.clientSecret,
+      refresh_token: params.refreshToken,
+    }),
+  });
+
+  return mapTokenResponse(data);
+}
+
+/**
+ * List the Confluence sites this access token can reach. The `id` of an entry is its cloud id.
+ *
+ * @stable
+ */
+export async function getAccessibleResources(accessToken: string): Promise {
+  return requestJson(ACCESSIBLE_RESOURCES_URL, {
+    method: 'GET',
+    headers: { Authorization: `Bearer ${accessToken}`, Accept: 'application/json' },
+  });
+}
diff --git a/src/core/oauth/index.ts b/src/core/oauth/index.ts
new file mode 100644
index 00000000..26a02d34
--- /dev/null
+++ b/src/core/oauth/index.ts
@@ -0,0 +1,16 @@
+export {
+  generateAuthorizationUrl,
+  exchangeAuthorizationCode,
+  refreshOAuth2Token,
+  getAccessibleResources,
+} from './helpers.js';
+
+export { parseCallbackUrl } from './parseCallbackUrl.js';
+
+export type { CallbackParams, ParseCallbackUrlOptions } from './parseCallbackUrl.js';
+
+export { createOAuth2Manager } from './oauth2Manager.js';
+
+export type { OAuth2Manager, OAuth2ManagerOptions } from './oauth2Manager.js';
+
+export type { OAuth2TokenResponse, AccessibleResource, TokenRefreshEvent, OnTokenRefresh } from './types.js';
diff --git a/src/core/oauth/oauth2Manager.ts b/src/core/oauth/oauth2Manager.ts
new file mode 100644
index 00000000..7bd0a1cf
--- /dev/null
+++ b/src/core/oauth/oauth2Manager.ts
@@ -0,0 +1,200 @@
+import type { AccessibleResource, OnTokenRefresh } from './types.js';
+import { getAccessibleResources, refreshOAuth2Token } from './helpers.js';
+import { isOAuthError, OAuthError } from '../errors/index.js';
+import { PRODUCT } from '../productInfo.js';
+
+/** 3LO tokens are only accepted through the gateway, never on the site's own domain. */
+const GATEWAY_BASE = `https://api.atlassian.com/ex/${PRODUCT.gatewaySlug}`;
+/** Refresh this many ms before `expiresAt`, to absorb clock skew and in-flight latency. */
+const EXPIRY_SKEW_MS = 60_000;
+
+export interface OAuth2ManagerOptions {
+  accessToken?: string;
+  refreshToken?: string;
+  clientId?: string;
+  clientSecret?: string;
+  expiresAt?: number;
+  cloudId?: string;
+  siteUrl?: string;
+  onTokenRefresh?: OnTokenRefresh;
+}
+
+export interface OAuth2Manager {
+  /** Whether a refresh is even possible — needs all three of `refreshToken`, `clientId`, `clientSecret`. */
+  canRefresh(): boolean;
+  /** `Bearer `, refreshing first if the token is missing or within the skew window of expiry. */
+  getAuthorizationHeader(): Promise;
+  /** The gateway base URL for the resolved cloud id. */
+  getBaseUrl(): Promise;
+  /** Refresh regardless of expiry. Used by the 401 retry path. */
+  forceRefresh(): Promise;
+}
+
+function normalizeUrl(url: string): string {
+  return url.replace(/\/+$/, '').toLowerCase();
+}
+
+/**
+ * Holds the OAuth 2.0 token state for one client: refreshes before expiry, resolves the cloud id once, and reports
+ * rotated refresh tokens through `onTokenRefresh`.
+ *
+ * Both the refresh and the cloud-id lookup are single-flighted, so N concurrent requests hitting an expired token
+ * produce one token call, not N.
+ */
+export function createOAuth2Manager(options: OAuth2ManagerOptions): OAuth2Manager {
+  const { clientId, clientSecret, siteUrl, onTokenRefresh } = options;
+
+  let accessToken = options.accessToken;
+  let refreshToken = options.refreshToken;
+  let expiresAt = options.expiresAt;
+  let cloudId = options.cloudId;
+
+  let refreshPromise: Promise | undefined;
+  let cloudIdPromise: Promise | undefined;
+
+  const canRefresh = (): boolean => refreshToken !== undefined && clientId !== undefined && clientSecret !== undefined;
+
+  const needsRefresh = (): boolean => {
+    if (!canRefresh()) return false;
+
+    if (accessToken === undefined) return true;
+
+    // No expiry known means no basis to act on — wait for a 401 rather than
+    // refreshing a token that may be perfectly good.
+    if (expiresAt === undefined) return false;
+
+    return Date.now() >= expiresAt - EXPIRY_SKEW_MS;
+  };
+
+  const doRefresh = async (): Promise => {
+    if (!canRefresh()) {
+      throw new OAuthError(
+        'Cannot refresh the OAuth 2.0 access token: `refreshToken`, `clientId` and `clientSecret` are required.',
+      );
+    }
+
+    const response = await refreshOAuth2Token({
+      clientId: clientId!,
+      clientSecret: clientSecret!,
+      refreshToken: refreshToken!,
+    });
+
+    accessToken = response.accessToken;
+
+    if (response.refreshToken) {
+      refreshToken = response.refreshToken;
+    }
+
+    expiresAt = Date.now() + response.expiresIn * 1000;
+
+    // Awaited, so a caller persisting the rotated token has finished before the
+    // request that triggered the refresh goes out.
+    await onTokenRefresh?.({ accessToken, refreshToken, expiresAt });
+  };
+
+  const refresh = async (): Promise => {
+    // Cleared in `finally`, so a failed refresh does not poison later attempts.
+    refreshPromise ??= doRefresh();
+
+    try {
+      await refreshPromise;
+    } finally {
+      refreshPromise = undefined;
+    }
+  };
+
+  const ensureAccessToken = async (): Promise => {
+    if (needsRefresh()) await refresh();
+
+    if (accessToken === undefined) {
+      throw new OAuthError(
+        'No OAuth 2.0 access token is available and it cannot be refreshed. Provide an `accessToken`, or the full ' +
+          'refresh credentials (`refreshToken`, `clientId`, `clientSecret`).',
+      );
+    }
+
+    return accessToken;
+  };
+
+  /**
+   * The sites this token can reach, refreshing once if the token turns out to be stale.
+   *
+   * This lookup runs before the request loop, so the client's own 401-and-retry never covers it. Without this, a token
+   * whose expiry is unknown — the shape you get when a caller supplies `accessToken` without `expiresAt` — would fail
+   * the cloud-id lookup permanently instead of refreshing the way any other request would.
+   */
+  const listResources = async (): Promise => {
+    try {
+      return await getAccessibleResources(await ensureAccessToken());
+    } catch (err) {
+      if (!isOAuthError(err) || err.status !== 401 || !canRefresh()) throw err;
+
+      await refresh();
+
+      return getAccessibleResources(await ensureAccessToken());
+    }
+  };
+
+  const selectResource = (resources: AccessibleResource[]): AccessibleResource => {
+    if (resources.length === 0) {
+      throw new OAuthError(
+        'No accessible Confluence resources were returned for this OAuth 2.0 token. Check the granted scopes and ' +
+          'that the user has access to at least one Confluence site.',
+      );
+    }
+
+    if (siteUrl !== undefined) {
+      const target = normalizeUrl(siteUrl);
+      const match = resources.find(resource => normalizeUrl(resource.url) === target);
+
+      if (!match) {
+        throw new OAuthError(
+          `No accessible resource matches siteUrl "${siteUrl}". Available: ${resources.map(r => r.url).join(', ')}.`,
+        );
+      }
+
+      return match;
+    }
+
+    if (resources.length > 1) {
+      throw new OAuthError(
+        'Multiple accessible Confluence resources found; pass `cloudId` or `siteUrl` to disambiguate. Available: ' +
+          `${resources.map(r => r.url).join(', ')}.`,
+      );
+    }
+
+    return resources[0];
+  };
+
+  const resolveCloudId = async (): Promise => {
+    if (cloudId !== undefined) return cloudId;
+
+    cloudIdPromise ??= (async () => {
+      const resources = await listResources();
+
+      cloudId = selectResource(resources).id;
+
+      return cloudId;
+    })();
+
+    try {
+      return await cloudIdPromise;
+    } finally {
+      cloudIdPromise = undefined;
+    }
+  };
+
+  return {
+    canRefresh,
+
+    async getAuthorizationHeader() {
+      return `Bearer ${await ensureAccessToken()}`;
+    },
+
+    async getBaseUrl() {
+      return `${GATEWAY_BASE}/${await resolveCloudId()}`;
+    },
+
+    forceRefresh: refresh,
+  };
+}
diff --git a/src/core/oauth/parseCallbackUrl.ts b/src/core/oauth/parseCallbackUrl.ts
new file mode 100644
index 00000000..4f2c3c64
--- /dev/null
+++ b/src/core/oauth/parseCallbackUrl.ts
@@ -0,0 +1,95 @@
+import { OAuthError } from '../errors/index.js';
+
+export interface ParseCallbackUrlOptions {
+  /**
+   * The `state` you generated for this authorization request and stored against the user's session.
+   *
+   * Checked before anything else. This is what stops an attacker from replaying someone else's callback into your
+   * session, and it only works if the value is unguessable and bound to that one user.
+   */
+  expectedState: string;
+}
+
+export interface CallbackParams {
+  /** The authorization code, ready for {@link exchangeAuthorizationCode}. */
+  code: string;
+  /** The `state` that came back, already verified against `expectedState`. */
+  state: string;
+}
+
+/** Constant-time string comparison, so a mismatch leaks nothing through timing. */
+function equals(a: string, b: string): boolean {
+  if (a.length !== b.length) return false;
+
+  let diff = 0;
+
+  for (let i = 0; i < a.length; i += 1) {
+    diff |= a.charCodeAt(i) ^ b.charCodeAt(i);
+  }
+
+  return diff === 0;
+}
+
+/**
+ * Read the authorization code out of the URL Atlassian redirected the user to.
+ *
+ * Handles the three ways this step goes wrong, each of which is easy to forget by hand:
+ *
+ * - the user declined on the consent screen, so the URL carries `error=access_denied` and no code;
+ * - `state` is missing or does not match the one you issued;
+ * - the URL is simply not a callback — no code, no error.
+ *
+ * Each throws an {@link OAuthError}; for a decline, `error` is `access_denied`, which
+ * {@link isReauthorizationRequired} recognises.
+ *
+ * @example
+ *   ```typescript
+ *   const { code } = parseCallbackUrl(request.url, { expectedState: session.oauthState });
+ *
+ *   const tokens = await exchangeAuthorizationCode({ clientId, clientSecret, code, redirectUri });
+ *   ```;
+ *
+ * @stable
+ */
+export function parseCallbackUrl(url: string | URL, options: ParseCallbackUrlOptions): CallbackParams {
+  // A relative URL is what a framework request object usually gives you; the base
+  // is irrelevant here, only the query matters.
+  const parsed = typeof url === 'string' ? new URL(url, 'http://localhost') : url;
+  const params = parsed.searchParams;
+
+  const error = params.get('error');
+
+  if (error) {
+    const description = params.get('error_description') ?? undefined;
+
+    throw new OAuthError(
+      error === 'access_denied'
+        ? `The user declined authorization${description ? `: ${description}` : '.'}`
+        : `Authorization failed: ${error}${description ? ` — ${description}` : ''}`,
+      // A decline here really does need another trip through consent. Flagged
+      // explicitly because the same code from the token endpoint means a bad
+      // client secret, where re-authorizing would loop the user for nothing.
+      { error, errorDescription: description, reauthorizationRequired: error === 'access_denied' },
+    );
+  }
+
+  const state = params.get('state');
+
+  if (state === null || !equals(state, options.expectedState)) {
+    throw new OAuthError(
+      'The `state` in the callback does not match the one issued for this authorization request. The callback was ' +
+        'not initiated by this session — discard it.',
+      { error: 'invalid_state' },
+    );
+  }
+
+  const code = params.get('code');
+
+  if (!code) {
+    throw new OAuthError('The callback URL carries neither an authorization code nor an error.', {
+      error: 'invalid_request',
+    });
+  }
+
+  return { code, state };
+}
diff --git a/src/core/oauth/types.ts b/src/core/oauth/types.ts
new file mode 100644
index 00000000..4d818a3d
--- /dev/null
+++ b/src/core/oauth/types.ts
@@ -0,0 +1,36 @@
+/** Normalised (camelCase) response from the Atlassian token endpoint. */
+export interface OAuth2TokenResponse {
+  accessToken: string;
+  /**
+   * The rotated refresh token, present when `offline_access` was requested. Persist it — Atlassian invalidates the one
+   * you sent.
+   */
+  refreshToken?: string;
+  /** Access-token lifetime in seconds, as returned by Atlassian. Typically 3600. */
+  expiresIn: number;
+  /** Space-separated granted scopes. */
+  scope: string;
+  /** Always `bearer`. */
+  tokenType: string;
+}
+
+/** An entry from `GET /oauth/token/accessible-resources`. */
+export interface AccessibleResource {
+  /** The cloud id — this is what `cloudId` expects. */
+  id: string;
+  name: string;
+  /** Site URL, e.g. `https://your-domain.atlassian.net`. */
+  url: string;
+  scopes: string[];
+  avatarUrl: string;
+}
+
+/** Payload handed to `onTokenRefresh` after every successful refresh. */
+export interface TokenRefreshEvent {
+  accessToken: string;
+  refreshToken?: string;
+  /** Epoch milliseconds. */
+  expiresAt: number;
+}
+
+export type OnTokenRefresh = (event: TokenRefreshEvent) => void | Promise;
diff --git a/src/core/productInfo.ts b/src/core/productInfo.ts
new file mode 100644
index 00000000..d19e00bc
--- /dev/null
+++ b/src/core/productInfo.ts
@@ -0,0 +1,34 @@
+/**
+ * The handful of places where the shared core has to name its own product.
+ *
+ * This file is generated. Everything else under `core/` is identical across the libraries, and stays that way by
+ * reading these values rather than hard-coding a product name.
+ */
+interface ProductInfo {
+  packageName: string;
+  gatewaySlug: string;
+  scopeHint: string;
+}
+
+/** Typed as plain strings on purpose: a product may leave the optional fields empty, and the code must still check. */
+export const PRODUCT: ProductInfo = {
+  /** The npm package name, e.g. `confluence.js`. */
+  packageName: 'confluence.js',
+
+  /**
+   * The Atlassian gateway slug, as in `https://api.atlassian.com/ex//{cloudId}`.
+   *
+   * Empty for products that are not behind the Atlassian gateway, where OAuth 2.0 (3LO) does not apply.
+   */
+  gatewaySlug: 'confluence',
+
+  /** Product-specific advice appended to a scope-mismatch 401, where the scope families differ per product. */
+  scopeHint: 'Note that v2 endpoints need granular scopes (read:page:confluence) while v1 endpoints need classic ones (read:confluence-content.all).',
+};
+
+/**
+ * The package name reduced to something safe inside a multipart boundary and a symbol key.
+ *
+ * A boundary may not contain a dot without being quoted, and `confluence.js` has one.
+ */
+export const PRODUCT_SLUG = PRODUCT.packageName.replace(/[^a-zA-Z0-9]+/g, '-');
diff --git a/src/core/schemas/auth.ts b/src/core/schemas/auth.ts
new file mode 100644
index 00000000..ed439aeb
--- /dev/null
+++ b/src/core/schemas/auth.ts
@@ -0,0 +1,85 @@
+import { z } from 'zod';
+import type { OnTokenRefresh } from '../oauth/types.js';
+
+export const authBasicSchema = z.object({
+  type: z.literal('basic'),
+  email: z.string().email(),
+  apiToken: z.string().min(1),
+});
+
+export const authBearerTokenSchema = z.object({
+  type: z.literal('bearer'),
+  token: z.string().min(1),
+});
+
+export const authBearerProviderSchema = z.object({
+  type: z.literal('bearer'),
+  getToken: z.custom<() => Promise>(val => typeof val === 'function', {
+    message: 'getToken must be a function',
+  }),
+});
+
+export const authBearerSchema = z.union([authBearerTokenSchema, authBearerProviderSchema]);
+
+/**
+ * Atlassian OAuth 2.0 (3LO).
+ *
+ * Either hand over an `accessToken` and manage its lifetime yourself, or hand over the full refresh credential set and
+ * let the client refresh on its own. The two refinements below encode exactly that: the second one exists because a
+ * partial credential set is always a mistake — it looks configured, then fails on the first refresh.
+ */
+export const authOAuth2Schema = z
+  .object({
+    type: z.literal('oauth2'),
+    accessToken: z.string().min(1).optional(),
+    refreshToken: z.string().min(1).optional(),
+    clientId: z.string().min(1).optional(),
+    clientSecret: z.string().min(1).optional(),
+    /** Access-token expiry as epoch milliseconds, e.g. `Date.now() + expiresIn * 1000`. */
+    expiresAt: z.number().optional(),
+    /** Atlassian cloud id. When set, the `accessible-resources` lookup is skipped. */
+    cloudId: z.string().min(1).optional(),
+    /** Site URL, e.g. `https://your-domain.atlassian.net`, used to pick a cloud id when the token can reach several. */
+    siteUrl: z.string().min(1).optional(),
+    /** Called after every refresh. Persist the rotated `refreshToken` here — the previous one is dead. */
+    onTokenRefresh: z
+      .custom(val => typeof val === 'function', { message: 'onTokenRefresh must be a function' })
+      .optional(),
+  })
+  .refine(
+    data =>
+      data.accessToken !== undefined ||
+      (data.refreshToken !== undefined && data.clientId !== undefined && data.clientSecret !== undefined),
+    {
+      message:
+        'OAuth 2.0 requires either an `accessToken` or a full refresh credential set (`refreshToken`, `clientId`, `clientSecret`).',
+    },
+  )
+  .refine(
+    data => {
+      const anyRefreshField =
+        data.refreshToken !== undefined || data.clientId !== undefined || data.clientSecret !== undefined;
+
+      if (!anyRefreshField) return true;
+
+      return data.refreshToken !== undefined && data.clientId !== undefined && data.clientSecret !== undefined;
+    },
+    {
+      message:
+        'When using OAuth 2.0 token refresh, `refreshToken`, `clientId` and `clientSecret` must all be provided together.',
+    },
+  );
+
+export const authSchema = z.union([authBasicSchema, authBearerSchema, authOAuth2Schema]);
+
+export type AuthBasic = z.infer;
+
+export type AuthOAuth2 = z.infer;
+
+export type AuthBearerToken = z.infer;
+
+export type AuthBearerProvider = z.infer;
+
+export type AuthBearer = z.infer;
+
+export type Auth = z.infer;
diff --git a/src/core/schemas/clientConfig.ts b/src/core/schemas/clientConfig.ts
new file mode 100644
index 00000000..31fe0331
--- /dev/null
+++ b/src/core/schemas/clientConfig.ts
@@ -0,0 +1,53 @@
+import { z } from 'zod';
+import { authSchema } from './auth.js';
+import type { AuthBasic, AuthBearer, AuthOAuth2 } from './auth.js';
+
+export const transientRetrySchema = z.object({
+  /** Total number of attempts including the first. Default: 1 (no retries). */
+  maxAttempts: z.number().int().positive().optional(),
+  /** Delay before the first retry in ms. Default: 500. */
+  initialDelayMs: z.number().int().nonnegative().optional(),
+  /** Exponential backoff multiplier. Default: 2. */
+  backoffFactor: z.number().positive().optional(),
+});
+
+export type TransientRetryConfig = z.infer;
+
+export const clientConfigSchema = z
+  .object({
+    /**
+     * The bare site URL, e.g. `https://your-domain.atlassian.net` — the API path belongs to the request, not here.
+     *
+     * Optional only under OAuth 2.0: 3LO tokens are not accepted on the site's own domain, so the client routes through
+     * `https://api.atlassian.com/ex/confluence/{cloudId}` and derives that URL itself.
+     */
+    host: z.url().optional(),
+    auth: authSchema.optional(),
+    headers: z.record(z.string(), z.string()).optional(),
+    getAuthOn401: z.custom<() => Promise>>(val => typeof val === 'function').optional(),
+    /**
+     * Opt-in retry for transient transport failures only — network errors (ECONNRESET, ETIMEDOUT, ENOTFOUND, EAI_AGAIN,
+     * EPIPE, UND_ERR_SOCKET, ERR_SSL_*) and HTTP 502/503/504. Never retries 4xx (including 401, 429) or 5xx other than
+     * 502/503/504 — those signal client or server logic and masking them would hide real regressions. Disabled by
+     * default.
+     */
+    retry: transientRetrySchema.optional(),
+  })
+  .refine(data => data.host !== undefined || data.auth?.type === 'oauth2', {
+    message: '`host` is required unless you authenticate with OAuth 2.0, which routes through the Atlassian gateway.',
+    path: ['host'],
+  });
+
+type ParsedClientConfig = z.infer;
+
+type CommonClientConfig = Omit;
+
+/**
+ * The shape accepted by `createClient`, `createV1Client` and `createV2Client`.
+ *
+ * Written by hand rather than inferred, because `host` is required for every strategy except OAuth 2.0 and a Zod
+ * refinement cannot express that in the type — only at runtime.
+ */
+export type ClientConfig =
+  | (CommonClientConfig & { host?: string; auth: AuthOAuth2 })
+  | (CommonClientConfig & { host: string; auth?: AuthBasic | AuthBearer });
diff --git a/src/core/schemas/httpMethod.ts b/src/core/schemas/httpMethod.ts
new file mode 100644
index 00000000..17c5f540
--- /dev/null
+++ b/src/core/schemas/httpMethod.ts
@@ -0,0 +1,5 @@
+import { z } from 'zod';
+
+export const httpMethodSchema = z.enum(['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'HEAD', 'OPTIONS']);
+
+export type HttpMethod = z.infer;
diff --git a/src/core/schemas/index.ts b/src/core/schemas/index.ts
new file mode 100644
index 00000000..a2b444d7
--- /dev/null
+++ b/src/core/schemas/index.ts
@@ -0,0 +1,15 @@
+export { httpMethodSchema } from './httpMethod.js';
+
+export type { HttpMethod } from './httpMethod.js';
+
+export { authSchema, authOAuth2Schema } from './auth.js';
+
+export type { Auth, AuthBasic, AuthBearer, AuthOAuth2 } from './auth.js';
+
+export { clientConfigSchema } from './clientConfig.js';
+
+export type { ClientConfig } from './clientConfig.js';
+
+export { sendRequestOptionsSchema } from './sendRequestOptions.js';
+
+export type { SendRequestOptions } from './sendRequestOptions.js';
diff --git a/src/core/schemas/sendRequestOptions.ts b/src/core/schemas/sendRequestOptions.ts
new file mode 100644
index 00000000..03d3899e
--- /dev/null
+++ b/src/core/schemas/sendRequestOptions.ts
@@ -0,0 +1,14 @@
+import { z } from 'zod';
+import { httpMethodSchema } from './httpMethod.js';
+
+export const sendRequestOptionsSchema = z.object({
+  url: z.string(),
+  method: httpMethodSchema.optional(),
+  headers: z.record(z.string(), z.string()).optional(),
+  body: z.unknown().optional(),
+  searchParams: z.record(z.string(), z.unknown()).optional(),
+});
+
+export type SendRequestOptions = z.infer & {
+  schema?: z.ZodType;
+};
diff --git a/src/core/serializeSearchParams.ts b/src/core/serializeSearchParams.ts
new file mode 100644
index 00000000..bafd5e90
--- /dev/null
+++ b/src/core/serializeSearchParams.ts
@@ -0,0 +1,61 @@
+export function serializeSearchParamValue(value: unknown): string | undefined {
+  if (value === undefined || value === null) {
+    return undefined;
+  }
+
+  if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') {
+    return String(value);
+  }
+
+  if (Array.isArray(value)) {
+    if (value.length === 0) {
+      return undefined;
+    }
+
+    if (value.every((item): item is string => typeof item === 'string')) {
+      return value.join(',');
+    }
+
+    return JSON.stringify(value);
+  }
+
+  if (typeof value === 'object') {
+    return JSON.stringify(value);
+  }
+
+  return String(value);
+}
+
+export function buildUrlWithSearchParams(baseUrl: string, searchParams?: Record): string {
+  if (!searchParams || Object.keys(searchParams).length === 0) {
+    return baseUrl;
+  }
+
+  const params = new URLSearchParams();
+
+  for (const [key, value] of Object.entries(searchParams)) {
+    if (Array.isArray(value)) {
+      for (const item of value) {
+        if (item !== undefined && item !== null) {
+          params.append(key, String(item));
+        }
+      }
+    } else {
+      const serialized = serializeSearchParamValue(value);
+
+      if (serialized !== undefined) {
+        params.set(key, serialized);
+      }
+    }
+  }
+
+  const query = params.toString();
+
+  if (!query) {
+    return baseUrl;
+  }
+
+  const separator = baseUrl.includes('?') ? '&' : '?';
+
+  return `${baseUrl}${separator}${query}`;
+}
diff --git a/src/core/withRetry.ts b/src/core/withRetry.ts
new file mode 100644
index 00000000..c185d312
--- /dev/null
+++ b/src/core/withRetry.ts
@@ -0,0 +1,68 @@
+import { isApiError, isNetworkError, isRateLimitError, TRANSIENT_HTTP_STATUSES } from './errors/index.js';
+
+export interface RetryOptions {
+  /** Total number of attempts including the first. Default: 3. */
+  maxAttempts?: number;
+  /** Delay before the first retry in milliseconds. Default: 1000. */
+  initialDelayMs?: number;
+  /** Exponential backoff multiplier. Default: 2. */
+  backoffFactor?: number;
+  /**
+   * Also retry a 429, waiting out `Retry-After` when Confluence sent one. Off by default: a rate limit asks you to slow
+   * the whole client down, and retrying one call in place papers over that.
+   */
+  retryRateLimit?: boolean;
+}
+
+/**
+ * Wraps an async operation with automatic retry on failures worth retrying.
+ *
+ * Retries a transient transport failure and a 502/503/504 gateway error — the same policy the client applies to its own
+ * requests, so wrapping a call does not change which failures count as temporary. Everything else is rethrown on the
+ * first attempt: 401, 403, 404 and 500 describe the request, not the moment. A 429 joins the list only under
+ * `retryRateLimit`, and then honours `Retry-After`.
+ *
+ * It is therefore a transient-failure helper, not a poller — to wait on eventually-consistent state, loop on the value
+ * rather than on a thrown error.
+ *
+ * @example
+ *   ```typescript
+ *   const page = await withRetry(
+ *     () => confluence.page.getPageById({ id: 12345 }),
+ *     { maxAttempts: 4, initialDelayMs: 500 },
+ *   );
+ *   ```;
+ *
+ * @stable
+ */
+export async function withRetry(operation: () => Promise, options: RetryOptions = {}): Promise {
+  const { maxAttempts = 3, initialDelayMs = 1000, backoffFactor = 2, retryRateLimit = false } = options;
+  let lastError: unknown;
+  let delayMs = initialDelayMs;
+
+  for (let attempt = 1; attempt <= maxAttempts; attempt++) {
+    try {
+      return await operation();
+    } catch (err) {
+      lastError = err;
+
+      const rateLimited = retryRateLimit && isRateLimitError(err);
+      const isRetryable =
+        rateLimited ||
+        (isNetworkError(err) && err.transient) ||
+        (isApiError(err) && TRANSIENT_HTTP_STATUSES.has(err.status));
+
+      if (!isRetryable || attempt === maxAttempts) {
+        throw err;
+      }
+
+      // Atlassian's own advice beats the backoff curve whenever it gave any.
+      const waitMs = (isRateLimitError(err) ? err.retryAfterMs : undefined) ?? delayMs;
+
+      await new Promise(resolve => setTimeout(resolve, waitMs));
+      delayMs = Math.round(delayMs * backoffFactor);
+    }
+  }
+
+  throw lastError;
+}
diff --git a/src/index.ts b/src/index.ts
index 8364c921..e819b7b7 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -1,11 +1,75 @@
-export * from './clients';
-export * from './config';
-export * from './requestConfig';
-export * from './callback';
-export * from './pagination';
-export * from './services';
-export * from './interfaces';
-
-export * as Api from './api';
-export * as Models from './api/models';
-export * as Parameters from './api/parameters';
+/**
+ * Confluence REST API client for Node.js and browsers.
+ *
+ * Both API versions are first-class: Atlassian has not deprecated v1, and the two cover different ground. Each has its
+ * own factory, and both take the same bare site URL — the API path is part of the request, not of `host`:
+ *
+ * ```ts
+ * import { createV2Client } from 'confluence.js';
+ *
+ * const confluence = createV2Client({
+ *   host: 'https://your-domain.atlassian.net',
+ *   auth: { type: 'basic', email, apiToken },
+ * });
+ *
+ * await confluence.page.getPages({ spaceId: [123] });
+ * ```
+ *
+ * For a smaller bundle, import the flat functions from `confluence.js/v1` or `confluence.js/v2` and drive them with a
+ * single client from `confluence.js/core` — one client serves both versions.
+ *
+ * `confluence.js/v1` and `confluence.js/v2` also expose every request parameter and response type. They are not
+ * re-exported here: the two versions collide on a handful of names (`createSpace`, `getTasks`).
+ */
+
+export { createV1Client, type V1Client } from './v1/createV1Client.js';
+
+export { createV2Client, type V2Client } from './v2/createV2Client.js';
+
+export {
+  ApiError,
+  AuthError,
+  ForbiddenError,
+  NotFoundError,
+  RateLimitError,
+  ScopeError,
+  ServerError,
+  NetworkError,
+  OAuthError,
+  ConfigError,
+  SchemaMismatchError,
+  isApiError,
+  isAuthError,
+  isForbiddenError,
+  isNotFoundError,
+  isRateLimitError,
+  isServerError,
+  isNetworkError,
+  isOAuthError,
+  isConfigError,
+  isSchemaMismatchError,
+  isReauthorizationRequired,
+  isScopeError,
+} from './core/index.js';
+
+export type { Auth, ClientConfig } from './core/index.js';
+
+export {
+  generateAuthorizationUrl,
+  exchangeAuthorizationCode,
+  refreshOAuth2Token,
+  getAccessibleResources,
+  parseCallbackUrl,
+} from './core/index.js';
+
+export type {
+  OAuth2TokenResponse,
+  AccessibleResource,
+  TokenRefreshEvent,
+  OnTokenRefresh,
+  CallbackParams,
+} from './core/index.js';
+
+export { createMultipartRequestBody, toFormDataFile } from './core/index.js';
+
+export type { AttachmentContent, AttachmentInput, MultipartRequestBody } from './core/index.js';
diff --git a/src/interfaces/extractBaseType.ts b/src/interfaces/extractBaseType.ts
deleted file mode 100644
index 889379df..00000000
--- a/src/interfaces/extractBaseType.ts
+++ /dev/null
@@ -1 +0,0 @@
-export type ExtractBaseType = T extends (infer U)[] ? U : T;
diff --git a/src/interfaces/index.ts b/src/interfaces/index.ts
deleted file mode 100644
index 02758423..00000000
--- a/src/interfaces/index.ts
+++ /dev/null
@@ -1,2 +0,0 @@
-export * from './extractBaseType';
-export * from './oneOrMany';
diff --git a/src/interfaces/oneOrMany.ts b/src/interfaces/oneOrMany.ts
deleted file mode 100644
index c014d044..00000000
--- a/src/interfaces/oneOrMany.ts
+++ /dev/null
@@ -1 +0,0 @@
-export type OneOrMany = T | T[];
diff --git a/src/pagination.ts b/src/pagination.ts
deleted file mode 100644
index 2ceb0839..00000000
--- a/src/pagination.ts
+++ /dev/null
@@ -1,8 +0,0 @@
-/* eslint-disable @typescript-eslint/no-explicit-any */
-export interface Pagination {
-  results: T[];
-  start: number;
-  limit: number;
-  size: number;
-  _links: Record;
-}
diff --git a/src/paramSerializer.ts b/src/paramSerializer.ts
deleted file mode 100644
index f84a92ce..00000000
--- a/src/paramSerializer.ts
+++ /dev/null
@@ -1,15 +0,0 @@
-export function paramSerializer(key: string, values?: string | string[]) {
-  if (typeof values === 'string') {
-    return () => `${key}=${values}`;
-  }
-
-  if (!values) {
-    return undefined;
-  }
-
-  if (!values.length) {
-    return '';
-  }
-
-  return () => values.map(value => `${key}=${value}`).join('&');
-}
diff --git a/src/requestConfig.ts b/src/requestConfig.ts
deleted file mode 100644
index 256383f9..00000000
--- a/src/requestConfig.ts
+++ /dev/null
@@ -1,3 +0,0 @@
-import type { AxiosRequestConfig } from 'axios';
-
-export type RequestConfig = AxiosRequestConfig;
diff --git a/src/services/authenticationService/authenticationService.ts b/src/services/authenticationService/authenticationService.ts
deleted file mode 100644
index 7bb0615d..00000000
--- a/src/services/authenticationService/authenticationService.ts
+++ /dev/null
@@ -1,33 +0,0 @@
-import type { Authentication } from '~/config';
-import {
-  createBasicAuthenticationToken,
-  createJWTAuthentication,
-  createOAuth2AuthenticationToken,
-} from './authentications';
-
-export async function getAuthenticationToken(
-  authentication: Authentication | undefined,
-  requestData?: {
-    baseURL: string;
-    url: string;
-    method: string;
-  },
-): Promise {
-  if (!authentication) {
-    return undefined;
-  }
-
-  if ('basic' in authentication) {
-    return createBasicAuthenticationToken(authentication);
-  }
-
-  if ('oauth2' in authentication) {
-    return createOAuth2AuthenticationToken(authentication);
-  }
-
-  if ('jwt' in authentication) {
-    return createJWTAuthentication(authentication, requestData!);
-  }
-
-  return undefined;
-}
diff --git a/src/services/authenticationService/authentications/createBasicAuthenticationToken.ts b/src/services/authenticationService/authentications/createBasicAuthenticationToken.ts
deleted file mode 100644
index bed2946d..00000000
--- a/src/services/authenticationService/authentications/createBasicAuthenticationToken.ts
+++ /dev/null
@@ -1,8 +0,0 @@
-import { Base64Encoder } from '../base64Encoder';
-import type { Basic } from '~';
-
-export function createBasicAuthenticationToken({ basic: { email, apiToken } }: Basic) {
-  const token = Base64Encoder.encode(`${email}:${apiToken}`);
-
-  return `Basic ${token}`;
-}
diff --git a/src/services/authenticationService/authentications/createJWTAuthentication.ts b/src/services/authenticationService/authentications/createJWTAuthentication.ts
deleted file mode 100644
index ae48f7bd..00000000
--- a/src/services/authenticationService/authentications/createJWTAuthentication.ts
+++ /dev/null
@@ -1,27 +0,0 @@
-import * as jwt from '@atlassian/atlassian-jwt';
-import type { JWT } from '~';
-
-export function createJWTAuthentication(
-  { jwt: { issuer, secret, expiryTimeSeconds } }: JWT,
-  requestData: {
-    method: string;
-    url: string;
-  },
-) {
-  const { method, url } = requestData;
-
-  const now = Math.floor(Date.now() / 1000);
-  const expire = now + (expiryTimeSeconds ?? 180);
-
-  const request = jwt.fromMethodAndUrl(method, url);
-  const tokenData = {
-    iss: issuer,
-    qsh: jwt.createQueryStringHash(request),
-    iat: now,
-    exp: expire,
-  };
-
-  const token = jwt.encodeSymmetric(tokenData, secret);
-
-  return `JWT ${token}`;
-}
diff --git a/src/services/authenticationService/authentications/createOAuth2AuthenticationToken.ts b/src/services/authenticationService/authentications/createOAuth2AuthenticationToken.ts
deleted file mode 100644
index 5564180d..00000000
--- a/src/services/authenticationService/authentications/createOAuth2AuthenticationToken.ts
+++ /dev/null
@@ -1,5 +0,0 @@
-import type { OAuth2 } from '~';
-
-export function createOAuth2AuthenticationToken({ oauth2: { accessToken } }: OAuth2) {
-  return `Bearer ${accessToken}`;
-}
diff --git a/src/services/authenticationService/authentications/index.ts b/src/services/authenticationService/authentications/index.ts
deleted file mode 100644
index 4354127b..00000000
--- a/src/services/authenticationService/authentications/index.ts
+++ /dev/null
@@ -1,3 +0,0 @@
-export * from './createBasicAuthenticationToken';
-export * from './createJWTAuthentication';
-export * from './createOAuth2AuthenticationToken';
diff --git a/src/services/authenticationService/base64Encoder.ts b/src/services/authenticationService/base64Encoder.ts
deleted file mode 100644
index f20d74e9..00000000
--- a/src/services/authenticationService/base64Encoder.ts
+++ /dev/null
@@ -1,69 +0,0 @@
-/* eslint-disable */
-/** @copyright The code was taken from the portal http://www.webtoolkit.info/javascript-base64.html */
-
-export namespace Base64Encoder {
-  const base64Sequence = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
-
-  const utf8Encode = (value: string) => {
-    value = value.replace(/\r\n/g, '\n');
-
-    let utftext = '';
-
-    for (let n = 0; n < value.length; n++) {
-      const c = value.charCodeAt(n);
-
-      if (c < 128) {
-        utftext += String.fromCharCode(c);
-      } else if (c > 127 && c < 2048) {
-        utftext += String.fromCharCode((c >> 6) | 192);
-
-        utftext += String.fromCharCode((c & 63) | 128);
-      } else {
-        utftext += String.fromCharCode((c >> 12) | 224);
-
-        utftext += String.fromCharCode(((c >> 6) & 63) | 128);
-
-        utftext += String.fromCharCode((c & 63) | 128);
-      }
-    }
-
-    return utftext;
-  };
-
-  export const encode = (input: string) => {
-    let output = '';
-    let chr1;
-    let chr2;
-    let chr3;
-    let enc1;
-    let enc2;
-    let enc3;
-    let enc4;
-    let i = 0;
-
-    input = utf8Encode(input);
-
-    while (i < input.length) {
-      chr1 = input.charCodeAt(i++);
-      chr2 = input.charCodeAt(i++);
-      chr3 = input.charCodeAt(i++);
-
-      enc1 = chr1 >> 2;
-      enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
-      enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
-      enc4 = chr3 & 63;
-
-      if (isNaN(chr2)) {
-        enc3 = enc4 = 64;
-      } else if (isNaN(chr3)) {
-        enc4 = 64;
-      }
-
-      output += `${base64Sequence.charAt(enc1)}${base64Sequence.charAt(enc2)}${base64Sequence.charAt(
-        enc3,
-      )}${base64Sequence.charAt(enc4)}`;
-    }
-
-    return output;
-  };
-}
diff --git a/src/services/authenticationService/index.ts b/src/services/authenticationService/index.ts
deleted file mode 100644
index 920abd06..00000000
--- a/src/services/authenticationService/index.ts
+++ /dev/null
@@ -1 +0,0 @@
-export * from './authenticationService';
diff --git a/src/services/index.ts b/src/services/index.ts
deleted file mode 100644
index 920abd06..00000000
--- a/src/services/index.ts
+++ /dev/null
@@ -1 +0,0 @@
-export * from './authenticationService';
diff --git a/src/v1/api/analytics.ts b/src/v1/api/analytics.ts
new file mode 100644
index 00000000..7357a935
--- /dev/null
+++ b/src/v1/api/analytics.ts
@@ -0,0 +1,33 @@
+import { GetViewsSchema, type GetViews } from '../models/getViews';
+import { GetViewersSchema, type GetViewers } from '../models/getViewers';
+import type { GetViews as GetViewsParameters } from '../parameters/getViews';
+import type { GetViewers as GetViewersParameters } from '../parameters/getViewers';
+import type { Client, SendRequestOptions } from '#/core';
+
+/** Get the total number of views a piece of content has. */
+export async function getViews(client: Client, parameters: GetViewsParameters): Promise {
+  const config: SendRequestOptions = {
+    url: `/wiki/rest/api/analytics/content/${parameters.contentId}/views`,
+    method: 'GET',
+    searchParams: {
+      fromDate: parameters.fromDate,
+    },
+    schema: GetViewsSchema,
+  };
+
+  return await client.sendRequest(config);
+}
+
+/** Get the total number of distinct viewers a piece of content has. */
+export async function getViewers(client: Client, parameters: GetViewersParameters): Promise {
+  const config: SendRequestOptions = {
+    url: `/wiki/rest/api/analytics/content/${parameters.contentId}/viewers`,
+    method: 'GET',
+    searchParams: {
+      fromDate: parameters.fromDate,
+    },
+    schema: GetViewersSchema,
+  };
+
+  return await client.sendRequest(config);
+}
diff --git a/src/v1/api/audit.ts b/src/v1/api/audit.ts
new file mode 100644
index 00000000..d0b4e13a
--- /dev/null
+++ b/src/v1/api/audit.ts
@@ -0,0 +1,151 @@
+import { AuditRecordArraySchema, type AuditRecordArray } from '../models/auditRecordArray';
+import { AuditRecordSchema, type AuditRecord } from '../models/auditRecord';
+import { RetentionPeriodSchema, type RetentionPeriod } from '../models/retentionPeriod';
+import type { GetAuditRecords } from '../parameters/getAuditRecords';
+import type { CreateAuditRecord } from '../parameters/createAuditRecord';
+import type { ExportAuditRecords } from '../parameters/exportAuditRecords';
+import type { SetRetentionPeriod } from '../parameters/setRetentionPeriod';
+import type { GetAuditRecordsForTimePeriod } from '../parameters/getAuditRecordsForTimePeriod';
+import type { Client, SendRequestOptions } from '#/core';
+
+/**
+ * Returns all records in the audit log, optionally for a certain date range. This contains information about events
+ * like space exports, group membership changes, app installations, etc. For more information, see [Audit
+ * log](https://confluence.atlassian.com/confcloud/audit-log-802164269.html) in the Confluence administrator's guide.
+ *
+ * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'Confluence Administrator' global permission.
+ */
+export async function getAuditRecords(client: Client, parameters?: GetAuditRecords): Promise {
+  const config: SendRequestOptions = {
+    url: '/wiki/rest/api/audit',
+    method: 'GET',
+    searchParams: {
+      startDate: parameters?.startDate,
+      endDate: parameters?.endDate,
+      searchString: parameters?.searchString,
+      start: parameters?.start,
+      limit: parameters?.limit,
+    },
+    schema: AuditRecordArraySchema,
+  };
+
+  return await client.sendRequest(config);
+}
+
+/**
+ * Creates a record in the audit log.
+ *
+ * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'Confluence Administrator' global permission.
+ */
+export async function createAuditRecord(client: Client, parameters: CreateAuditRecord): Promise {
+  const config: SendRequestOptions = {
+    url: '/wiki/rest/api/audit',
+    method: 'POST',
+    headers: {
+      'X-Atlassian-Token': 'no-check',
+    },
+    body: {
+      author: parameters.author,
+      remoteAddress: parameters.remoteAddress,
+      creationDate: parameters.creationDate,
+      summary: parameters.summary,
+      description: parameters.description,
+      category: parameters.category,
+      sysAdmin: parameters.sysAdmin,
+      affectedObject: parameters.affectedObject,
+      changedValues: parameters.changedValues,
+      associatedObjects: parameters.associatedObjects,
+    },
+    schema: AuditRecordSchema,
+  };
+
+  return await client.sendRequest(config);
+}
+
+/**
+ * Exports audit records as a CSV file or ZIP file.
+ *
+ * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'Confluence Administrator' global permission.
+ */
+export async function exportAuditRecords(client: Client, parameters?: ExportAuditRecords): Promise {
+  const config: SendRequestOptions = {
+    url: '/wiki/rest/api/audit/export',
+    method: 'GET',
+    searchParams: {
+      startDate: parameters?.startDate,
+      endDate: parameters?.endDate,
+      searchString: parameters?.searchString,
+      format: parameters?.format,
+    },
+  };
+
+  return await client.sendRequest(config);
+}
+
+/**
+ * Returns the retention period for records in the audit log. The retention period is how long an audit record is kept
+ * for, from creation date until it is deleted.
+ *
+ * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'Confluence Administrator' global permission.
+ */
+export async function getRetentionPeriod(client: Client): Promise {
+  const config: SendRequestOptions = {
+    url: '/wiki/rest/api/audit/retention',
+    method: 'GET',
+    schema: RetentionPeriodSchema,
+  };
+
+  return await client.sendRequest(config);
+}
+
+/**
+ * Sets the retention period for records in the audit log. The retention period can be set to a maximum of 1 year.
+ *
+ * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'Confluence Administrator' global permission.
+ */
+export async function setRetentionPeriod(client: Client, parameters: SetRetentionPeriod): Promise {
+  const config: SendRequestOptions = {
+    url: '/wiki/rest/api/audit/retention',
+    method: 'PUT',
+    headers: {
+      'X-Atlassian-Token': 'no-check',
+    },
+    body: {
+      number: parameters.number,
+      units: parameters.units,
+    },
+    schema: RetentionPeriodSchema,
+  };
+
+  return await client.sendRequest(config);
+}
+
+/**
+ * Returns records from the audit log, for a time period back from the current date. For example, you can use this
+ * method to get the last 3 months of records.
+ *
+ * This contains information about events like space exports, group membership changes, app installations, etc. For more
+ * information, see [Audit log](https://confluence.atlassian.com/confcloud/audit-log-802164269.html) in the Confluence
+ * administrator's guide.
+ *
+ * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'Confluence Administrator' global permission.
+ */
+export async function getAuditRecordsForTimePeriod(
+  client: Client,
+  parameters?: GetAuditRecordsForTimePeriod,
+): Promise {
+  const config: SendRequestOptions = {
+    url: '/wiki/rest/api/audit/since',
+    method: 'GET',
+    searchParams: {
+      number: parameters?.number,
+      units: parameters?.units,
+      searchString: parameters?.searchString,
+      start: parameters?.start,
+      limit: parameters?.limit,
+    },
+    schema: AuditRecordArraySchema,
+  };
+
+  return await client.sendRequest(config);
+}
diff --git a/src/v1/api/content.ts b/src/v1/api/content.ts
new file mode 100644
index 00000000..9612def0
--- /dev/null
+++ b/src/v1/api/content.ts
@@ -0,0 +1,148 @@
+import { LongTaskSchema, type LongTask } from '../models/longTask';
+import { ContentSchema, type Content } from '../models/content';
+import { ContentArraySchema, type ContentArray } from '../models/contentArray';
+import type { ArchivePages } from '../parameters/archivePages';
+import type { PublishLegacyDraft } from '../parameters/publishLegacyDraft';
+import type { PublishSharedDraft } from '../parameters/publishSharedDraft';
+import type { SearchContentByCQL } from '../parameters/searchContentByCQL';
+import type { Client, SendRequestOptions } from '#/core';
+
+/**
+ * Archives a list of pages. The pages to be archived are specified as a list of content IDs. This API accepts the
+ * archival request and returns a task ID. The archival process happens asynchronously. Use the /longtask/ REST
+ * API to get the copy task status.
+ *
+ * Each content ID needs to resolve to page objects that are not already in an archived state. The content IDs need not
+ * belong to the same space.
+ *
+ * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'Archive' permission for each of the pages in
+ * the corresponding space it belongs to.
+ */
+export async function archivePages(client: Client, parameters: ArchivePages): Promise {
+  const config: SendRequestOptions = {
+    url: '/wiki/rest/api/content/archive',
+    method: 'POST',
+    headers: {
+      'X-Atlassian-Token': 'no-check',
+    },
+    body: {
+      pages: parameters.pages,
+    },
+    schema: LongTaskSchema,
+  };
+
+  return await client.sendRequest(config);
+}
+
+/**
+ * Publishes a legacy draft of a page created from a blueprint. Legacy drafts will eventually be removed in favor of
+ * shared drafts. For now, this method works the same as [Publish shared
+ * draft](#api-content-blueprint-instance-draftId-put).
+ *
+ * By default, the following objects are expanded: `body.storage`, `history`, `space`, `version`, `ancestors`.
+ *
+ * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to view the draft and 'Add'
+ * permission for the space that the content will be created in.
+ */
+export async function publishLegacyDraft(client: Client, parameters: PublishLegacyDraft): Promise {
+  const config: SendRequestOptions = {
+    url: `/wiki/rest/api/content/blueprint/instance/${parameters.draftId}`,
+    method: 'POST',
+    headers: {
+      'X-Atlassian-Token': 'no-check',
+    },
+    searchParams: {
+      status: parameters.status,
+      expand: parameters.expand,
+    },
+    body: parameters.body,
+    schema: ContentSchema,
+  };
+
+  return await client.sendRequest(config);
+}
+
+/**
+ * Publishes a shared draft of a page created from a blueprint.
+ *
+ * By default, the following objects are expanded: `body.storage`, `history`, `space`, `version`, `ancestors`.
+ *
+ * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to view the draft and 'Add'
+ * permission for the space that the content will be created in.
+ */
+export async function publishSharedDraft(client: Client, parameters: PublishSharedDraft): Promise {
+  const config: SendRequestOptions = {
+    url: `/wiki/rest/api/content/blueprint/instance/${parameters.draftId}`,
+    method: 'PUT',
+    headers: {
+      'X-Atlassian-Token': 'no-check',
+    },
+    searchParams: {
+      status: parameters.status,
+      expand: parameters.expand,
+    },
+    body: parameters.body,
+    schema: ContentSchema,
+  };
+
+  return await client.sendRequest(config);
+}
+
+/**
+ * Returns the list of content that matches a Confluence Query Language (CQL) query. For information on CQL, see:
+ * [Advanced searching using CQL](https://developer.atlassian.com/cloud/confluence/advanced-searching-using-cql/).
+ *
+ * Example initial call:
+ *
+ *     /wiki/rest/api/content/search?cql=type=page&limit=25
+ *
+ * Example response:
+ *
+ *     {
+ *       "results": [
+ *         { ... },
+ *         { ... },
+ *         ...
+ *         { ... }
+ *       ],
+ *       "limit": 25,
+ *       "size": 25,
+ *       ...
+ *       "_links": {
+ *         "base": "",
+ *         "context": "",
+ *         "next": "/rest/api/content/search?cql=type=page&limit=25&cursor=raNDoMsTRiNg",
+ *         "self": ""
+ *       }
+ *     }
+ *
+ * When additional results are available, returns `next` and `prev` URLs to retrieve them in subsequent calls. The URLs
+ * each contain a cursor that points to the appropriate set of results. Use `limit` to specify the number of results
+ * returned in each call. Example subsequent call (taken from example response):
+ *
+ *     /wiki/rest/api/content/search?cql=type=page&limit=25&cursor=raNDoMsTRiNg
+ *
+ * The response to this will have a `prev` URL similar to the `next` in the example response.
+ *
+ * If the expand query parameter is used with the `body.export_view` and/or `body.styled_view` properties, then the
+ * query limit parameter will be restricted to a maximum value of 25.
+ *
+ * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to access the Confluence site ('Can
+ * use' global permission). Only content that the user has permission to view will be returned.
+ */
+export async function searchContentByCQL(client: Client, parameters: SearchContentByCQL): Promise {
+  const config: SendRequestOptions = {
+    url: '/wiki/rest/api/content/search',
+    method: 'GET',
+    searchParams: {
+      cql: parameters.cql,
+      cqlcontext: parameters.cqlcontext,
+      expand: parameters.expand,
+      cursor: parameters.cursor,
+      limit: parameters.limit,
+    },
+    schema: ContentArraySchema,
+  };
+
+  return await client.sendRequest(config);
+}
diff --git a/src/v1/api/contentAttachments.ts b/src/v1/api/contentAttachments.ts
new file mode 100644
index 00000000..cc746ced
--- /dev/null
+++ b/src/v1/api/contentAttachments.ts
@@ -0,0 +1,211 @@
+import { ContentArraySchema, type ContentArray } from '../models/contentArray';
+import { ContentSchema, type Content } from '../models/content';
+import type { CreateAttachment } from '../parameters/createAttachment';
+import type { CreateOrUpdateAttachments } from '../parameters/createOrUpdateAttachments';
+import type { UpdateAttachmentProperties } from '../parameters/updateAttachmentProperties';
+import type { UpdateAttachmentData } from '../parameters/updateAttachmentData';
+import type { DownloadAttatchment } from '../parameters/downloadAttatchment';
+import { type Client, type SendRequestOptions, toFormDataFile, BufferSchema, type Buffer } from '#/core';
+
+/**
+ * Adds an attachment to a piece of content. This method only adds a new attachment. If you want to update an existing
+ * attachment, use [Create or update attachments](#api-content-id-child-attachment-put).
+ *
+ * The media type 'multipart/form-data' is defined in [RFC 7578](https://www.ietf.org/rfc/rfc7578.txt). Most client
+ * libraries have classes that make it easier to implement multipart posts, like the
+ * [MultipartEntityBuilder](https://hc.apache.org/httpcomponents-client-5.1.x/current/httpclient5/apidocs/) Java class
+ * provided by Apache HTTP Components.
+ *
+ * Note, according to [RFC 7578](https://tools.ietf.org/html/rfc7578#section-4.5), in the case where the form data is
+ * text, the charset parameter for the "text/plain" Content-Type may be used to indicate the character encoding used in
+ * that part. In the case of this API endpoint, the `comment` body parameter should be sent with `type=text/plain` and
+ * `charset=utf-8` values. This will force the charset to be UTF-8.
+ *
+ * Example: This curl command attaches a file ('example.txt') to a container (id='123') with a comment and
+ * `minorEdits`=true.
+ *
+ * ```bash
+ * curl -D- \
+ *   -u admin:admin \
+ *   -X POST \
+ *   -H 'X-Atlassian-Token: nocheck' \
+ *   -F 'file=@"example.txt"' \
+ *   -F 'minorEdit="true"' \
+ *   -F 'comment="Example attachment comment"; type=text/plain; charset=utf-8' \
+ *   https://myhost/wiki/rest/api/content/123/child/attachment
+ * ```
+ *
+ * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to update the content.
+ */
+export async function createAttachment(client: Client, parameters: CreateAttachment): Promise {
+  const formData = new FormData();
+  const items = Array.isArray(parameters.attachments) ? parameters.attachments : [parameters.attachments];
+
+  for (const attachment of items) {
+    formData.append('file', await toFormDataFile(attachment), attachment.filename);
+  }
+
+  const config: SendRequestOptions = {
+    url: `/wiki/rest/api/content/${parameters.id}/child/attachment`,
+    method: 'POST',
+    headers: {
+      'X-Atlassian-Token': 'no-check',
+    },
+    searchParams: {
+      status: parameters.status,
+    },
+    body: formData,
+    schema: ContentArraySchema,
+  };
+
+  return await client.sendRequest(config);
+}
+
+/**
+ * Adds an attachment to a piece of content. If the attachment already exists for the content, then the attachment is
+ * updated (i.e. a new version of the attachment is created).
+ *
+ * The media type 'multipart/form-data' is defined in [RFC 7578](https://www.ietf.org/rfc/rfc7578.txt). Most client
+ * libraries have classes that make it easier to implement multipart posts, like the
+ * [MultipartEntityBuilder](https://hc.apache.org/httpcomponents-client-5.1.x/current/httpclient5/apidocs/) Java class
+ * provided by Apache HTTP Components.
+ *
+ * Note, according to [RFC 7578](https://tools.ietf.org/html/rfc7578#section-4.5), in the case where the form data is
+ * text, the charset parameter for the "text/plain" Content-Type may be used to indicate the character encoding used in
+ * that part. In the case of this API endpoint, the `comment` body parameter should be sent with `type=text/plain` and
+ * `charset=utf-8` values. This will force the charset to be UTF-8.
+ *
+ * Example: This curl command attaches a file ('example.txt') to a piece of content (id='123') with a comment and
+ * `minorEdits`=true. If the 'example.txt' file already exists, it will update it with a new version of the attachment.
+ *
+ * ```bash
+ * curl -D- \
+ *   -u admin:admin \
+ *   -X PUT \
+ *   -H 'X-Atlassian-Token: nocheck' \
+ *   -F 'file=@"example.txt"' \
+ *   -F 'minorEdit="true"' \
+ *   -F 'comment="Example attachment comment"; type=text/plain; charset=utf-8' \
+ *   http://myhost/rest/api/content/123/child/attachment
+ * ```
+ *
+ * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to update the content.
+ */
+export async function createOrUpdateAttachments(
+  client: Client,
+  parameters: CreateOrUpdateAttachments,
+): Promise {
+  const formData = new FormData();
+  const items = Array.isArray(parameters.attachments) ? parameters.attachments : [parameters.attachments];
+
+  for (const attachment of items) {
+    formData.append('file', await toFormDataFile(attachment), attachment.filename);
+  }
+
+  const config: SendRequestOptions = {
+    url: `/wiki/rest/api/content/${parameters.id}/child/attachment`,
+    method: 'PUT',
+    headers: {
+      'X-Atlassian-Token': 'no-check',
+    },
+    searchParams: {
+      status: parameters.status,
+    },
+    body: formData,
+    schema: ContentArraySchema,
+  };
+
+  return await client.sendRequest(config);
+}
+
+/**
+ * Updates the attachment properties, i.e. the non-binary data of an attachment like the filename, media-type, comment,
+ * and parent container.
+ *
+ * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to update the content.
+ */
+export async function updateAttachmentProperties(
+  client: Client,
+  parameters: UpdateAttachmentProperties,
+): Promise {
+  const config: SendRequestOptions = {
+    url: `/wiki/rest/api/content/${parameters.id}/child/attachment/${parameters.attachmentId}`,
+    method: 'PUT',
+    headers: {
+      'X-Atlassian-Token': 'no-check',
+    },
+    body: parameters.body,
+    schema: ContentSchema,
+  };
+
+  return await client.sendRequest(config);
+}
+
+/**
+ * Updates the binary data of an attachment, given the attachment ID, and optionally the comment and the minor edit
+ * field.
+ *
+ * This method is essentially the same as [Create or update attachments](#api-content-id-child-attachment-put), except
+ * that it matches the attachment ID rather than the name.
+ *
+ * The media type 'multipart/form-data' is defined in [RFC 7578](https://www.ietf.org/rfc/rfc7578.txt). Most client
+ * libraries have classes that make it easier to implement multipart posts, like the
+ * [MultipartEntityBuilder](https://hc.apache.org/httpcomponents-client-5.1.x/current/httpclient5/apidocs/) Java class
+ * provided by Apache HTTP Components.
+ *
+ * Note, according to [RFC 7578](https://tools.ietf.org/html/rfc7578#section-4.5), in the case where the form data is
+ * text, the charset parameter for the "text/plain" Content-Type may be used to indicate the character encoding used in
+ * that part. In the case of this API endpoint, the `comment` body parameter should be sent with `type=text/plain` and
+ * `charset=utf-8` values. This will force the charset to be UTF-8.
+ *
+ * Example: This curl command updates an attachment (id='att456') that is attached to a piece of content (id='123') with
+ * a comment and `minorEdits`=true.
+ *
+ * ```bash
+ * curl -D- \
+ *   -u admin:admin \
+ *   -X POST \
+ *   -H 'X-Atlassian-Token: nocheck' \
+ *   -F 'file=@"example.txt"' \
+ *   -F 'minorEdit="true"' \
+ *   -F 'comment="Example attachment comment"; type=text/plain; charset=utf-8' \
+ *   http://myhost/rest/api/content/123/child/attachment/att456/data
+ * ```
+ *
+ * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to update the content.
+ */
+export async function updateAttachmentData(client: Client, parameters: UpdateAttachmentData): Promise {
+  const formData = new FormData();
+  const items = Array.isArray(parameters.attachment) ? parameters.attachment : [parameters.attachment];
+
+  for (const attachment of items) {
+    formData.append('file', await toFormDataFile(attachment), attachment.filename);
+  }
+
+  const config: SendRequestOptions = {
+    url: `/wiki/rest/api/content/${parameters.id}/child/attachment/${parameters.attachmentId}/data`,
+    method: 'POST',
+    headers: {
+      'X-Atlassian-Token': 'no-check',
+    },
+    body: formData,
+    schema: ContentSchema,
+  };
+
+  return await client.sendRequest(config);
+}
+
+/** Redirects the client to a URL that serves an attachment's binary data. */
+export async function downloadAttatchment(client: Client, parameters: DownloadAttatchment): Promise {
+  const config: SendRequestOptions = {
+    url: `/wiki/rest/api/content/${parameters.id}/child/attachment/${parameters.attachmentId}/download`,
+    method: 'GET',
+    searchParams: {
+      version: parameters.version,
+      status: parameters.status,
+    },
+    schema: BufferSchema,
+  };
+
+  return await client.sendRequest(config);
+}
diff --git a/src/v1/api/contentBody.ts b/src/v1/api/contentBody.ts
new file mode 100644
index 00000000..070b704b
--- /dev/null
+++ b/src/v1/api/contentBody.ts
@@ -0,0 +1,137 @@
+import { AsyncIdSchema, type AsyncId } from '../models/asyncId';
+import { AsyncContentBodySchema, type AsyncContentBody } from '../models/asyncContentBody';
+import { AsyncContentBodyArraySchema, type AsyncContentBodyArray } from '../models/asyncContentBodyArray';
+import { AsyncIdArraySchema, type AsyncIdArray } from '../models/asyncIdArray';
+import type { AsyncConvertContentBodyRequest } from '../parameters/asyncConvertContentBodyRequest';
+import type { AsyncConvertContentBodyResponse } from '../parameters/asyncConvertContentBodyResponse';
+import type { BulkAsyncConvertContentBodyResponse } from '../parameters/bulkAsyncConvertContentBodyResponse';
+import type { BulkAsyncConvertContentBodyRequest } from '../parameters/bulkAsyncConvertContentBodyRequest';
+import type { Client, SendRequestOptions } from '#/core';
+
+/**
+ * Converts a content body from one format to another format asynchronously. Returns the asyncId for the asynchronous
+ * task.
+ *
+ * Supported conversions:
+ *
+ * - Atlas_doc_format: editor, export_view, storage, styled_view, view
+ * - Storage: atlas_doc_format, editor, export_view, styled_view, view
+ * - Editor: storage
+ *
+ * No other conversions are supported at the moment. Once a conversion is completed, it will be available for 5 minutes
+ * at the result endpoint.
+ *
+ * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: If request specifies 'contentIdContext',
+ * 'View' permission for the space, and permission to view the content.
+ */
+export async function asyncConvertContentBodyRequest(
+  client: Client,
+  parameters: AsyncConvertContentBodyRequest,
+): Promise {
+  const config: SendRequestOptions = {
+    url: `/wiki/rest/api/contentbody/convert/async/${parameters.to}`,
+    method: 'POST',
+    headers: {
+      'X-Atlassian-Token': 'no-check',
+    },
+    searchParams: {
+      expand: parameters.expand,
+      spaceKeyContext: parameters.spaceKeyContext,
+      contentIdContext: parameters.contentIdContext,
+      allowCache: parameters.allowCache,
+      embeddedContentRender: parameters.embeddedContentRender,
+    },
+    body: {
+      value: parameters.value,
+      representation: parameters.representation,
+    },
+    schema: AsyncIdSchema,
+  };
+
+  return await client.sendRequest(config);
+}
+
+/**
+ * Returns the content body for the corresponding `asyncId` of a completed conversion task. If the task is not
+ * completed, the task status is returned instead.
+ *
+ * Once a conversion task is completed, the result can be obtained for up to 5 minutes, or until an identical conversion
+ * request is made again with the `allowCache` parameter set to false.
+ *
+ * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: If request specifies 'contentIdContext',
+ * 'View' permission for the space, and permission to view the content.
+ */
+export async function asyncConvertContentBodyResponse(
+  client: Client,
+  parameters: AsyncConvertContentBodyResponse,
+): Promise {
+  const config: SendRequestOptions = {
+    url: `/wiki/rest/api/contentbody/convert/async/${parameters.id}`,
+    method: 'GET',
+    schema: AsyncContentBodySchema,
+  };
+
+  return await client.sendRequest(config);
+}
+
+/**
+ * Returns the content body for the corresponding `asyncId` of a completed conversion task. If the task is not
+ * completed, the task status is returned instead.
+ *
+ * Once a conversion task is completed, the result can be obtained for up to 5 minutes, or until an identical conversion
+ * request is made again with the `allowCache` parameter set to false.
+ *
+ * Note that there is a maximum limit of 50 task results per request to this endpoint.
+ *
+ * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to access the Confluence site ('Can
+ * use' global permission).
+ */
+export async function bulkAsyncConvertContentBodyResponse(
+  client: Client,
+  parameters: BulkAsyncConvertContentBodyResponse,
+): Promise {
+  const config: SendRequestOptions = {
+    url: '/wiki/rest/api/contentbody/convert/async/bulk/tasks',
+    method: 'GET',
+    searchParams: {
+      ids: parameters.ids,
+    },
+    schema: AsyncContentBodyArraySchema,
+  };
+
+  return await client.sendRequest(config);
+}
+
+/**
+ * Asynchronously converts content bodies from one format to another format in bulk. Use the Content body REST API to
+ * get the status of conversion tasks. Note that there is a maximum limit of 10 conversions per request to this
+ * endpoint.
+ *
+ * Supported conversions:
+ *
+ * - Storage: editor, export_view, styled_view, view
+ * - Editor: storage
+ *
+ * Once a conversion task is completed, it is available for polling for up to 5 minutes.
+ *
+ * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'View' permission for the space, and
+ * permission to view the content if the `spaceKeyContext` or `contentIdContext` are present.
+ */
+export async function bulkAsyncConvertContentBodyRequest(
+  client: Client,
+  parameters: BulkAsyncConvertContentBodyRequest,
+): Promise {
+  const config: SendRequestOptions = {
+    url: '/wiki/rest/api/contentbody/convert/async/bulk/tasks',
+    method: 'POST',
+    headers: {
+      'X-Atlassian-Token': 'no-check',
+    },
+    body: {
+      conversionInputs: parameters.conversionInputs,
+    },
+    schema: AsyncIdArraySchema,
+  };
+
+  return await client.sendRequest(config);
+}
diff --git a/src/v1/api/contentChildrenAndDescendants.ts b/src/v1/api/contentChildrenAndDescendants.ts
new file mode 100644
index 00000000..b16b4916
--- /dev/null
+++ b/src/v1/api/contentChildrenAndDescendants.ts
@@ -0,0 +1,195 @@
+import { MovePageSchema, type MovePage } from '../models/movePage';
+import { ContentChildrenSchema, type ContentChildren } from '../models/contentChildren';
+import { ContentArraySchema, type ContentArray } from '../models/contentArray';
+import { LongTaskSchema, type LongTask } from '../models/longTask';
+import { ContentSchema, type Content } from '../models/content';
+import type { MovePage as MovePageParameters } from '../parameters/movePage';
+import type { GetContentDescendants } from '../parameters/getContentDescendants';
+import type { GetDescendantsOfType } from '../parameters/getDescendantsOfType';
+import type { CopyPageHierarchy } from '../parameters/copyPageHierarchy';
+import type { CopyPage } from '../parameters/copyPage';
+import type { Client, SendRequestOptions } from '#/core';
+
+/**
+ * Move a page to a new location relative to a target page:
+ *
+ * - `before` - move the page under the same parent as the target, before the target in the list of children
+ * - `after` - move the page under the same parent as the target, after the target in the list of children
+ * - `append` - move the page to be a child of the target
+ *
+ * Caution: This API can move pages to the top level of a space. Top-level pages are difficult to find in the UI because
+ * they do not show up in the page tree display. To avoid this, never use `before` or `after` positions when the
+ * `targetId` is a top-level page.
+ */
+export async function movePage(client: Client, parameters: MovePageParameters): Promise {
+  const config: SendRequestOptions = {
+    url: `/wiki/rest/api/content/${parameters.pageId}/move/${parameters.position}/${parameters.targetId}`,
+    method: 'PUT',
+    headers: {
+      'X-Atlassian-Token': 'no-check',
+    },
+    schema: MovePageSchema,
+  };
+
+  return await client.sendRequest(config);
+}
+
+/**
+ * Returns a map of the descendants of a piece of content. This is similar to [Get content
+ * children](#api-content-id-child-get), except that this method returns child pages at all levels, rather than just the
+ * direct child pages.
+ *
+ * A piece of content has different types of descendants, depending on its type:
+ *
+ * - `page`: descendant is `page`, `whiteboard`, `database`, `embed`, `folder`, `comment`, `attachment`
+ * - `whiteboard`: descendant is `page`, `whiteboard`, `database`, `embed`, `folder`, `comment`, `attachment`
+ * - `database`: descendant is `page`, `whiteboard`, `database`, `embed`, `folder`, `comment`, `attachment`
+ * - `embed`: descendant is `page`, `whiteboard`, `database`, `embed`, `folder`, `comment`, `attachment`
+ * - `folder`: descendant is `page`, `whiteboard`, `database`, `embed`, `folder`, `comment`, `attachment`
+ * - `blogpost`: descendant is `comment`, `attachment`
+ * - `attachment`: descendant is `comment`
+ * - `comment`: descendant is `attachment`
+ *
+ * The map will always include all descendant types that are valid for the content. However, if the content has no
+ * instances of a descendant type, the map will contain an empty array for that descendant type.
+ *
+ * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'View' permission for the space, and
+ * permission to view the content if it is a page.
+ */
+export async function getContentDescendants(
+  client: Client,
+  parameters: GetContentDescendants,
+): Promise {
+  const config: SendRequestOptions = {
+    url: `/wiki/rest/api/content/${parameters.id}/descendant`,
+    method: 'GET',
+    searchParams: {
+      expand: parameters.expand,
+    },
+    schema: ContentChildrenSchema,
+  };
+
+  return await client.sendRequest(config);
+}
+
+/**
+ * Returns all descendants of a given type, for a piece of content. This is similar to [Get content children by
+ * type](#api-content-id-child-type-get), except that this method returns child pages at all levels, rather than just
+ * the direct child pages.
+ *
+ * A piece of content has different types of descendants, depending on its type:
+ *
+ * - `page`: descendant is `page`, `whiteboard`, `database`, `embed`, `folder`, `comment`, `attachment`
+ * - `whiteboard`: descendant is `page`, `whiteboard`, `database`, `embed`, `folder`, `comment`, `attachment`
+ * - `database`: descendant is `page`, `whiteboard`, `database`, `embed`, `folder`, `comment`, `attachment`
+ * - `embed`: descendant is `page`, `whiteboard`, `database`, `embed`, `folder`, `comment`, `attachment`
+ * - `folder`: descendant is `page`, `whiteboard`, `database`, `embed`, `folder`, `comment`, `attachment`
+ * - `blogpost`: descendant is `comment`, `attachment`
+ * - `attachment`: descendant is `comment`
+ * - `comment`: descendant is `attachment`
+ *
+ * Custom content types that are provided by apps can also be returned.
+ *
+ * If the expand query parameter is used with the `body.export_view` and/or `body.styled_view` properties, then the
+ * query limit parameter will be restricted to a maximum value of 25.
+ *
+ * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'View' permission for the space, and
+ * permission to view the content if it is a page.
+ */
+export async function getDescendantsOfType(client: Client, parameters: GetDescendantsOfType): Promise {
+  const config: SendRequestOptions = {
+    url: `/wiki/rest/api/content/${parameters.id}/descendant/${parameters.type}`,
+    method: 'GET',
+    searchParams: {
+      depth: parameters.depth,
+      expand: parameters.expand,
+      start: parameters.start,
+      limit: parameters.limit,
+    },
+    schema: ContentArraySchema,
+  };
+
+  return await client.sendRequest(config);
+}
+
+/**
+ * Copy page hierarchy allows the copying of an entire hierarchy of pages and their associated properties, permissions
+ * and attachments. The id path parameter refers to the content id of the page to copy, and the new parent of this
+ * copied page is defined using the destinationPageId in the request body. The titleOptions object defines the rules of
+ * renaming page titles during the copy; for example, search and replace can be used in conjunction to rewrite the
+ * copied page titles.
+ *
+ * Response example: 

+ *  {
+ *       "id" : "1180606",
+ *       "links" : {
+ *            "status" : "/rest/api/longtask/1180606"
+ *       }
+ *  }
+ *  
+ * + * Use the /longtask/ REST API to get the copy task status. + */ +export async function copyPageHierarchy(client: Client, parameters: CopyPageHierarchy): Promise { + const config: SendRequestOptions = { + url: `/wiki/rest/api/content/${parameters.id}/pagehierarchy/copy`, + method: 'POST', + headers: { + 'X-Atlassian-Token': 'no-check', + }, + body: { + copyAttachments: parameters.copyAttachments, + copyPermissions: parameters.copyPermissions, + copyProperties: parameters.copyProperties, + copyLabels: parameters.copyLabels, + copyCustomContents: parameters.copyCustomContents, + copyDescendants: parameters.copyDescendants, + destinationPageId: parameters.destinationPageId, + titleOptions: parameters.titleOptions, + }, + schema: LongTaskSchema, + }; + + return await client.sendRequest(config); +} + +/** + * Copies a single page and its associated properties, permissions, attachments, and custom contents. The `id` path + * parameter refers to the content ID of the page to copy. The target of the page to be copied is defined using the + * `destination` in the request body and can be one of the following types. + * + * - `space`: page will be copied to the specified space as a root page on the space + * - `parent_page`: page will be copied as a child of the specified parent page + * - `parent_content`: page will be copied as a child of the specified parent content + * - `existing_page`: page will be copied and replace the specified page + * + * By default, the following objects are expanded: `space`, `history`, `version`. + * + * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'Add' permission for the space that the + * content will be copied in and permission to update the content if copying to an `existing_page`. + */ +export async function copyPage(client: Client, parameters: CopyPage): Promise { + const config: SendRequestOptions = { + url: `/wiki/rest/api/content/${parameters.id}/copy`, + method: 'POST', + headers: { + 'X-Atlassian-Token': 'no-check', + }, + searchParams: { + expand: parameters.expand, + }, + body: { + copyAttachments: parameters.copyAttachments, + copyPermissions: parameters.copyPermissions, + copyProperties: parameters.copyProperties, + copyLabels: parameters.copyLabels, + copyCustomContents: parameters.copyCustomContents, + destination: parameters.destination, + pageTitle: parameters.pageTitle, + body: parameters.body, + }, + schema: ContentSchema, + }; + + return await client.sendRequest(config); +} diff --git a/src/v1/api/contentLabels.ts b/src/v1/api/contentLabels.ts new file mode 100644 index 00000000..80b95b02 --- /dev/null +++ b/src/v1/api/contentLabels.ts @@ -0,0 +1,81 @@ +import { LabelArraySchema, type LabelArray } from '../models/labelArray'; +import type { AddLabelsToContent } from '../parameters/addLabelsToContent'; +import type { RemoveLabelFromContentUsingQueryParameter } from '../parameters/removeLabelFromContentUsingQueryParameter'; +import type { RemoveLabelFromContent } from '../parameters/removeLabelFromContent'; +import type { Client, SendRequestOptions } from '#/core'; + +/** + * Adds labels to a piece of content. Does not modify the existing labels. + * + * Notes: + * + * - Labels can also be added when creating content ([Create content](#api-content-post)). + * - Labels can be updated when updating content ([Update content](#api-content-id-put)). This will delete the existing + * labels and replace them with the labels in the request. + * + * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to update the content. + */ +export async function addLabelsToContent(client: Client, parameters: AddLabelsToContent): Promise { + const config: SendRequestOptions = { + url: `/wiki/rest/api/content/${parameters.id}/label`, + method: 'POST', + headers: { + 'X-Atlassian-Token': 'no-check', + }, + body: parameters.body, + schema: LabelArraySchema, + }; + + return await client.sendRequest(config); +} + +/** + * Removes a label from a piece of content. Labels can't be deleted from archived content. This is similar to [Remove + * label from content](#api-content-id-label-label-delete) except that the label name is specified via a query + * parameter. + * + * Use this method if the label name has "/" characters, as [Remove label from content using query + * parameter](#api-content-id-label-delete) does not accept "/" characters for the label name. + * + * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to update the content. + */ +export async function removeLabelFromContentUsingQueryParameter( + client: Client, + parameters: RemoveLabelFromContentUsingQueryParameter, +): Promise { + const config: SendRequestOptions = { + url: `/wiki/rest/api/content/${parameters.id}/label`, + method: 'DELETE', + headers: { + 'X-Atlassian-Token': 'no-check', + }, + searchParams: { + name: parameters.name, + }, + }; + + return await client.sendRequest(config); +} + +/** + * Removes a label from a piece of content. Labels can't be deleted from archived content. This is similar to [Remove + * label from content using query parameter](#api-content-id-label-delete) except that the label name is specified via a + * path parameter. + * + * Use this method if the label name does not have "/" characters, as the path parameter does not accept "/" characters + * for security reasons. Otherwise, use [Remove label from content using query + * parameter](#api-content-id-label-delete). + * + * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to update the content. + */ +export async function removeLabelFromContent(client: Client, parameters: RemoveLabelFromContent): Promise { + const config: SendRequestOptions = { + url: `/wiki/rest/api/content/${parameters.id}/label/${parameters.label}`, + method: 'DELETE', + headers: { + 'X-Atlassian-Token': 'no-check', + }, + }; + + return await client.sendRequest(config); +} diff --git a/src/v1/api/contentMacroBody.ts b/src/v1/api/contentMacroBody.ts new file mode 100644 index 00000000..26f68f72 --- /dev/null +++ b/src/v1/api/contentMacroBody.ts @@ -0,0 +1,138 @@ +import { MacroInstanceSchema, type MacroInstance } from '../models/macroInstance'; +import { ContentBodySchema, type ContentBody } from '../models/contentBody'; +import { AsyncIdSchema, type AsyncId } from '../models/asyncId'; +import type { GetMacroBodyByMacroId } from '../parameters/getMacroBodyByMacroId'; +import type { GetAndConvertMacroBodyByMacroId } from '../parameters/getAndConvertMacroBodyByMacroId'; +import type { GetAndAsyncConvertMacroBodyByMacroId } from '../parameters/getAndAsyncConvertMacroBodyByMacroId'; +import type { Client, SendRequestOptions } from '#/core'; + +/** + * Returns the body of a macro in storage format, for the given macro ID. This includes information like the name of the + * macro, the body of the macro, and any macro parameters. This method is mainly used by Cloud apps. + * + * About the macro ID: When a macro is created in a new version of content, Confluence will generate a random ID for it, + * unless an ID is specified (by an app). The macro ID will look similar to this: + * '50884bd9-0cb8-41d5-98be-f80943c14f96'. The ID is then persisted as new versions of content are created, and is only + * modified by Confluence if there are conflicting IDs. + * + * For Forge macros, the value for macro ID is the "local ID" of that particular ADF node. This value can be retrieved + * either client-side by calling view.getContext() and accessing "localId" on the resulting object, or server-side by + * examining the "local-id" parameter node inside the "parameters" node. + * + * Note that there are other attributes named "local-id", but only this particular one is used to store the macro ID. + * + * Example: com.atlassian.ecosystem e9c4aa10-73fa-417c-888d-48c719ae4165 + * + * Note, to preserve backwards compatibility this resource will also match on the hash of the macro body, even if a + * macro ID is found. This check will eventually become redundant, as macro IDs are generated for pages and + * transparently propagate out to all instances. + * + * This backwards compatibility logic does not apply to Forge macros; those can only be retrieved by their ID. + * + * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to view the content that the macro + * is in. + */ +export async function getMacroBodyByMacroId(client: Client, parameters: GetMacroBodyByMacroId): Promise { + const config: SendRequestOptions = { + url: `/wiki/rest/api/content/${parameters.id}/history/${parameters.version}/macro/id/${parameters.macroId}`, + method: 'GET', + schema: MacroInstanceSchema, + }; + + return await client.sendRequest(config); +} + +/** + * Returns the body of a macro in format specified in path, for the given macro ID. This includes information like the + * name of the macro, the body of the macro, and any macro parameters. + * + * About the macro ID: When a macro is created in a new version of content, Confluence will generate a random ID for it, + * unless an ID is specified (by an app). The macro ID will look similar to this: + * '50884bd9-0cb8-41d5-98be-f80943c14f96'. The ID is then persisted as new versions of content are created, and is only + * modified by Confluence if there are conflicting IDs. + * + * For Forge macros, the value for macro ID is the "local ID" of that particular ADF node. This value can be retrieved + * either client-side by calling view.getContext() and accessing "localId" on the resulting object, or server-side by + * examining the "local-id" parameter node inside the "parameters" node. + * + * Note that there are other attributes named "local-id", but only this particular one is used to store the macro ID. + * + * Example: com.atlassian.ecosystem e9c4aa10-73fa-417c-888d-48c719ae4165 + * + * Note, to preserve backwards compatibility this resource will also match on the hash of the macro body, even if a + * macro ID is found. This check will eventually become redundant, as macro IDs are generated for pages and + * transparently propagate out to all instances. + * + * This backwards compatibility logic does not apply to Forge macros; those can only be retrieved by their ID. + * + * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to view the content that the macro + * is in. + */ +export async function getAndConvertMacroBodyByMacroId( + client: Client, + parameters: GetAndConvertMacroBodyByMacroId, +): Promise { + const config: SendRequestOptions = { + url: `/wiki/rest/api/content/${parameters.id}/history/${parameters.version}/macro/id/${parameters.macroId}/convert/${parameters.to}`, + method: 'GET', + searchParams: { + expand: parameters.expand, + spaceKeyContext: parameters.spaceKeyContext, + embeddedContentRender: parameters.embeddedContentRender, + }, + schema: ContentBodySchema, + }; + + return await client.sendRequest(config); +} + +/** + * Returns Async Id of the conversion task which will convert the macro into a content body of the desired format. The + * result will be available for 5 minutes after completion of the conversion. + * + * About the macro ID: When a macro is created in a new version of content, Confluence will generate a random ID for it, + * unless an ID is specified (by an app). The macro ID will look similar to this: '884bd9-0cb8-41d5-98be-f80943c14f96'. + * The ID is then persisted as new versions of content are created, and is only modified by Confluence if there are + * conflicting IDs. + * + * For Forge macros, the value for macro ID is the "local ID" of that particular ADF node. This value can be retrieved + * either client-side by calling view.getContext() and accessing "localId" on the resulting object, or server-side by + * examining the "local-id" parameter node inside the "parameters" node. + * + * Note that there are other attributes named "local-id", but only this particular one is used to store the macro ID. + * + * Example: com.atlassian.ecosystem e9c4aa10-73fa-417c-888d-48c719ae4165 + * + * Note, to preserve backwards compatibility this resource will also match on the hash of the macro body, even if a + * macro ID is found. This check will eventually become redundant, as macro IDs are generated for pages and + * transparently propagate out to all instances. + * + * This backwards compatibility logic does not apply to Forge macros; those can only be retrieved by their ID. + * + * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to view the content that the macro + * is in. + */ +export async function getAndAsyncConvertMacroBodyByMacroId( + client: Client, + parameters: GetAndAsyncConvertMacroBodyByMacroId, +): Promise { + const config: SendRequestOptions = { + url: `/wiki/rest/api/content/${parameters.id}/history/${parameters.version}/macro/id/${parameters.macroId}/convert/async/${parameters.to}`, + method: 'GET', + searchParams: { + expand: parameters.expand, + allowCache: parameters.allowCache, + spaceKeyContext: parameters.spaceKeyContext, + embeddedContentRender: parameters.embeddedContentRender, + }, + schema: AsyncIdSchema, + }; + + return await client.sendRequest(config); +} diff --git a/src/v1/api/contentPermissions.ts b/src/v1/api/contentPermissions.ts new file mode 100644 index 00000000..f2725f25 --- /dev/null +++ b/src/v1/api/contentPermissions.ts @@ -0,0 +1,37 @@ +import { PermissionCheckResponseSchema, type PermissionCheckResponse } from '../models/permissionCheckResponse'; +import type { CheckContentPermission } from '../parameters/checkContentPermission'; +import type { Client, SendRequestOptions } from '#/core'; + +/** + * Check if a user or a group can perform an operation to the specified content. The `operation` to check must be + * provided. The user’s account ID or the ID of the group can be provided in the `subject` to check permissions against + * a specified user or group. The following permission checks are done to make sure that the user or group has the + * proper access: + * + * - Site permissions + * - Space permissions + * - Content restrictions + * + * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to access the Confluence site ('Can + * use' global permission) if checking permission for self, otherwise 'Confluence Administrator' global permission is + * required. + */ +export async function checkContentPermission( + client: Client, + parameters: CheckContentPermission, +): Promise { + const config: SendRequestOptions = { + url: `/wiki/rest/api/content/${parameters.id}/permission/check`, + method: 'POST', + headers: { + 'X-Atlassian-Token': 'no-check', + }, + body: { + subject: parameters.subject, + operation: parameters.operation, + }, + schema: PermissionCheckResponseSchema, + }; + + return await client.sendRequest(config); +} diff --git a/src/v1/api/contentRestrictions.ts b/src/v1/api/contentRestrictions.ts new file mode 100644 index 00000000..213deb45 --- /dev/null +++ b/src/v1/api/contentRestrictions.ts @@ -0,0 +1,299 @@ +import { ContentRestrictionArraySchema, type ContentRestrictionArray } from '../models/contentRestrictionArray'; +import { ContentRestrictionSchema, type ContentRestriction } from '../models/contentRestriction'; +import type { GetRestrictions } from '../parameters/getRestrictions'; +import type { AddRestrictions } from '../parameters/addRestrictions'; +import type { UpdateRestrictions } from '../parameters/updateRestrictions'; +import type { DeleteRestrictions } from '../parameters/deleteRestrictions'; +import type { GetRestrictionsByOperation } from '../parameters/getRestrictionsByOperation'; +import type { GetRestrictionsForOperation } from '../parameters/getRestrictionsForOperation'; +import type { GetIndividualGroupRestrictionStatusByGroupId } from '../parameters/getIndividualGroupRestrictionStatusByGroupId'; +import type { AddGroupToContentRestrictionByGroupId } from '../parameters/addGroupToContentRestrictionByGroupId'; +import type { RemoveGroupFromContentRestriction } from '../parameters/removeGroupFromContentRestriction'; +import type { GetContentRestrictionStatusForUser } from '../parameters/getContentRestrictionStatusForUser'; +import type { AddUserToContentRestriction } from '../parameters/addUserToContentRestriction'; +import type { RemoveUserFromContentRestriction } from '../parameters/removeUserFromContentRestriction'; +import type { Client, SendRequestOptions } from '#/core'; + +/** + * Returns the restrictions on a piece of content. + * + * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to view the content. + */ +export async function getRestrictions(client: Client, parameters: GetRestrictions): Promise { + const config: SendRequestOptions = { + url: `/wiki/rest/api/content/${parameters.id}/restriction`, + method: 'GET', + searchParams: { + expand: parameters.expand, + start: parameters.start, + limit: parameters.limit, + }, + schema: ContentRestrictionArraySchema, + }; + + return await client.sendRequest(config); +} + +/** + * Adds restrictions to a piece of content. Note, this does not change any existing restrictions on the content. + * + * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to edit the content. + */ +export async function addRestrictions(client: Client, parameters: AddRestrictions): Promise { + const config: SendRequestOptions = { + url: `/wiki/rest/api/content/${parameters.id}/restriction`, + method: 'POST', + headers: { + 'X-Atlassian-Token': 'no-check', + }, + searchParams: { + expand: parameters.expand, + }, + body: parameters.body, + schema: ContentRestrictionArraySchema, + }; + + return await client.sendRequest(config); +} + +/** + * Updates restrictions for a piece of content. This removes the existing restrictions and replaces them with the + * restrictions in the request. + * + * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to edit the content. + */ +export async function updateRestrictions( + client: Client, + parameters: UpdateRestrictions, +): Promise { + const config: SendRequestOptions = { + url: `/wiki/rest/api/content/${parameters.id}/restriction`, + method: 'PUT', + headers: { + 'X-Atlassian-Token': 'no-check', + }, + searchParams: { + expand: parameters.expand, + }, + body: parameters.body, + schema: ContentRestrictionArraySchema, + }; + + return await client.sendRequest(config); +} + +/** + * Removes all restrictions (read and update) on a piece of content. + * + * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to edit the content. + */ +export async function deleteRestrictions( + client: Client, + parameters: DeleteRestrictions, +): Promise { + const config: SendRequestOptions = { + url: `/wiki/rest/api/content/${parameters.id}/restriction`, + method: 'DELETE', + headers: { + 'X-Atlassian-Token': 'no-check', + }, + searchParams: { + expand: parameters.expand, + }, + schema: ContentRestrictionArraySchema, + }; + + return await client.sendRequest(config); +} + +/** + * Returns restrictions on a piece of content by operation. This method is similar to [Get + * restrictions](#api-content-id-restriction-get) except that the operations are properties of the return object, rather + * than items in a results array. + * + * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to view the content. + */ +export async function getRestrictionsByOperation( + client: Client, + parameters: GetRestrictionsByOperation, +): Promise { + const config: SendRequestOptions = { + url: `/wiki/rest/api/content/${parameters.id}/restriction/byOperation`, + method: 'GET', + searchParams: { + expand: parameters.expand, + }, + }; + + return await client.sendRequest(config); +} + +/** + * Returns the restictions on a piece of content for a given operation (read or update). + * + * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to view the content. + */ +export async function getRestrictionsForOperation( + client: Client, + parameters: GetRestrictionsForOperation, +): Promise { + const config: SendRequestOptions = { + url: `/wiki/rest/api/content/${parameters.id}/restriction/byOperation/${parameters.operationKey}`, + method: 'GET', + searchParams: { + expand: parameters.expand, + start: parameters.start, + limit: parameters.limit, + }, + schema: ContentRestrictionSchema, + }; + + return await client.sendRequest(config); +} + +/** + * Returns whether the specified content restriction applies to a group. For example, if a page with `id=123` has a + * `read` restriction for the `123456` group id, the following request will return `true`: + * + * `/wiki/rest/api/content/123/restriction/byOperation/read/byGroupId/123456` + * + * Note that a response of `true` does not guarantee that the group can view the page, as it does not account for + * account-inherited restrictions, space permissions, or even product access. For more information, see [Confluence + * permissions](https://confluence.atlassian.com/x/_AozKw). + * + * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to view the content. + */ +export async function getIndividualGroupRestrictionStatusByGroupId( + client: Client, + parameters: GetIndividualGroupRestrictionStatusByGroupId, +): Promise { + const config: SendRequestOptions = { + url: `/wiki/rest/api/content/${parameters.id}/restriction/byOperation/${parameters.operationKey}/byGroupId/${parameters.groupId}`, + method: 'GET', + }; + + return await client.sendRequest(config); +} + +/** + * Adds a group to a content restriction by Group Id. That is, grant read or update permission to the group for a piece + * of content. + * + * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to edit the content. + */ +export async function addGroupToContentRestrictionByGroupId( + client: Client, + parameters: AddGroupToContentRestrictionByGroupId, +): Promise { + const config: SendRequestOptions = { + url: `/wiki/rest/api/content/${parameters.id}/restriction/byOperation/${parameters.operationKey}/byGroupId/${parameters.groupId}`, + method: 'PUT', + headers: { + 'X-Atlassian-Token': 'no-check', + }, + }; + + return await client.sendRequest(config); +} + +/** + * Removes a group from a content restriction. That is, remove read or update permission for the group for a piece of + * content. + * + * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to edit the content. + */ +export async function removeGroupFromContentRestriction( + client: Client, + parameters: RemoveGroupFromContentRestriction, +): Promise { + const config: SendRequestOptions = { + url: `/wiki/rest/api/content/${parameters.id}/restriction/byOperation/${parameters.operationKey}/byGroupId/${parameters.groupId}`, + method: 'DELETE', + headers: { + 'X-Atlassian-Token': 'no-check', + }, + }; + + return await client.sendRequest(config); +} + +/** + * Returns whether the specified content restriction applies to a user. For example, if a page with `id=123` has a + * `read` restriction for a user with an account ID of `384093:32b4d9w0-f6a5-3535-11a3-9c8c88d10192`, the following + * request will return `true`: + * + * `/wiki/rest/api/content/123/restriction/byOperation/read/user?accountId=384093:32b4d9w0-f6a5-3535-11a3-9c8c88d10192` + * + * Note that a response of `true` does not guarantee that the user can view the page, as it does not account for + * account-inherited restrictions, space permissions, or even product access. For more information, see [Confluence + * permissions](https://confluence.atlassian.com/x/_AozKw). + * + * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to view the content. + */ +export async function getContentRestrictionStatusForUser( + client: Client, + parameters: GetContentRestrictionStatusForUser, +): Promise { + const config: SendRequestOptions = { + url: `/wiki/rest/api/content/${parameters.id}/restriction/byOperation/${parameters.operationKey}/user`, + method: 'GET', + searchParams: { + key: parameters.key, + username: parameters.username, + accountId: parameters.accountId, + }, + }; + + return await client.sendRequest(config); +} + +/** + * Adds a user to a content restriction. That is, grant read or update permission to the user for a piece of content. + * + * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to edit the content. + */ +export async function addUserToContentRestriction( + client: Client, + parameters: AddUserToContentRestriction, +): Promise { + const config: SendRequestOptions = { + url: `/wiki/rest/api/content/${parameters.id}/restriction/byOperation/${parameters.operationKey}/user`, + method: 'PUT', + headers: { + 'X-Atlassian-Token': 'no-check', + }, + searchParams: { + key: parameters.key, + username: parameters.username, + accountId: parameters.accountId, + }, + }; + + return await client.sendRequest(config); +} + +/** + * Removes a group from a content restriction. That is, remove read or update permission for the group for a piece of + * content. + * + * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to edit the content. + */ +export async function removeUserFromContentRestriction( + client: Client, + parameters: RemoveUserFromContentRestriction, +): Promise { + const config: SendRequestOptions = { + url: `/wiki/rest/api/content/${parameters.id}/restriction/byOperation/${parameters.operationKey}/user`, + method: 'DELETE', + headers: { + 'X-Atlassian-Token': 'no-check', + }, + searchParams: { + key: parameters.key, + username: parameters.username, + accountId: parameters.accountId, + }, + }; + + return await client.sendRequest(config); +} diff --git a/src/v1/api/contentStates.ts b/src/v1/api/contentStates.ts new file mode 100644 index 00000000..80ea21dc --- /dev/null +++ b/src/v1/api/contentStates.ts @@ -0,0 +1,184 @@ +import { ContentStateResponseSchema, type ContentStateResponse } from '../models/contentStateResponse'; +import { AvailableContentStatesSchema, type AvailableContentStates } from '../models/availableContentStates'; +import { ContentStateSchema, type ContentState } from '../models/contentState'; +import { ContentStateSettingsSchema, type ContentStateSettings } from '../models/contentStateSettings'; +import { ContentArraySchema, type ContentArray } from '../models/contentArray'; +import type { GetContentState } from '../parameters/getContentState'; +import type { SetContentState } from '../parameters/setContentState'; +import type { RemoveContentState } from '../parameters/removeContentState'; +import type { GetAvailableContentStates } from '../parameters/getAvailableContentStates'; +import type { GetSpaceContentStates } from '../parameters/getSpaceContentStates'; +import type { GetContentStateSettings } from '../parameters/getContentStateSettings'; +import type { GetContentsWithState } from '../parameters/getContentsWithState'; +import type { Client, SendRequestOptions } from '#/core'; +import { z } from 'zod'; + +/** + * Gets the current content state of the draft or current version of content. To specify the draft version, set the + * parameter status to draft, otherwise archived or current will get the relevant published state. + * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to view the content. + */ +export async function getContentState(client: Client, parameters: GetContentState): Promise { + const config: SendRequestOptions = { + url: `/wiki/rest/api/content/${parameters.id}/state`, + method: 'GET', + searchParams: { + status: parameters.status, + }, + schema: ContentStateResponseSchema, + }; + + return await client.sendRequest(config); +} + +/** + * Sets the content state of the content specified and creates a new version (publishes the content without changing the + * body) of the content with the new state. + * + * You may pass in either an id of a state, or the name and color of a desired new state. If all 3 are passed in, id + * will be used. If the name and color passed in already exist under the current user's existing custom states, the + * existing state will be reused. If custom states are disabled in the space of the content (which can be determined by + * getting the content state space settings of the content's space) then this set will fail. + * + * You may not remove a content state via this PUT request. You must use the DELETE method. A specified state is + * required in the body of this request. + * + * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to edit the content. + */ +export async function setContentState(client: Client, parameters: SetContentState): Promise { + const config: SendRequestOptions = { + url: `/wiki/rest/api/content/${parameters.id}/state`, + method: 'PUT', + headers: { + 'X-Atlassian-Token': 'no-check', + }, + searchParams: { + status: parameters.status, + }, + body: parameters.body, + schema: ContentStateResponseSchema, + }; + + return await client.sendRequest(config); +} + +/** + * Removes the content state of the content specified and creates a new version (publishes the content without changing + * the body) of the content with the new status. + * + * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to edit the content. + */ +export async function removeContentState( + client: Client, + parameters: RemoveContentState, +): Promise { + const config: SendRequestOptions = { + url: `/wiki/rest/api/content/${parameters.id}/state`, + method: 'DELETE', + headers: { + 'X-Atlassian-Token': 'no-check', + }, + searchParams: { + status: parameters.status, + }, + schema: ContentStateResponseSchema, + }; + + return await client.sendRequest(config); +} + +/** + * Gets content states that are available for the content to be set as. Will return all enabled Space Content States. + * Will only return most the 3 most recently published custom content states to match UI editor list. To get all custom + * content states, use the /content-states endpoint. + * + * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to edit the content. + */ +export async function getAvailableContentStates( + client: Client, + parameters: GetAvailableContentStates, +): Promise { + const config: SendRequestOptions = { + url: `/wiki/rest/api/content/${parameters.id}/state/available`, + method: 'GET', + schema: AvailableContentStatesSchema, + }; + + return await client.sendRequest(config); +} + +/** + * Get custom content states that authenticated user has created. + * + * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required** Must have user authentication. + */ +export async function getCustomContentStates(client: Client): Promise { + const config: SendRequestOptions = { + url: '/wiki/rest/api/content-states', + method: 'GET', + schema: z.array(ContentStateSchema), + }; + + return await client.sendRequest(config); +} + +/** + * Get content states that are suggested in the space. + * + * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'View' permission for the space. + */ +export async function getSpaceContentStates( + client: Client, + parameters: GetSpaceContentStates, +): Promise { + const config: SendRequestOptions = { + url: `/wiki/rest/api/space/${parameters.spaceKey}/state`, + method: 'GET', + schema: z.array(ContentStateSchema), + }; + + return await client.sendRequest(config); +} + +/** + * Get object describing whether content states are allowed at all, if custom content states or space content states are + * restricted, and a list of space content states allowed for the space if they are not restricted. + * + * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'Admin' permission for the space. + */ +export async function getContentStateSettings( + client: Client, + parameters: GetContentStateSettings, +): Promise { + const config: SendRequestOptions = { + url: `/wiki/rest/api/space/${parameters.spaceKey}/state/settings`, + method: 'GET', + schema: ContentStateSettingsSchema, + }; + + return await client.sendRequest(config); +} + +/** + * Returns all content that has the provided content state in a space. + * + * If the expand query parameter is used with the `body.export_view` and/or `body.styled_view` properties, then the + * query limit parameter will be restricted to a maximum value of 25. + * + * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'View' permission for the space. + */ +export async function getContentsWithState(client: Client, parameters: GetContentsWithState): Promise { + const config: SendRequestOptions = { + url: `/wiki/rest/api/space/${parameters.spaceKey}/state/content`, + method: 'GET', + searchParams: { + 'state-id': parameters['state-id'], + expand: parameters.expand, + limit: parameters.limit, + start: parameters.start, + }, + schema: ContentArraySchema, + }; + + return await client.sendRequest(config); +} diff --git a/src/v1/api/contentVersions.ts b/src/v1/api/contentVersions.ts new file mode 100644 index 00000000..2a557345 --- /dev/null +++ b/src/v1/api/contentVersions.ts @@ -0,0 +1,48 @@ +import { VersionSchema, type Version } from '../models/version'; +import type { RestoreContentVersion } from '../parameters/restoreContentVersion'; +import type { DeleteContentVersion } from '../parameters/deleteContentVersion'; +import type { Client, SendRequestOptions } from '#/core'; + +/** + * Restores a historical version to be the latest version. That is, a new version is created with the content of the + * historical version. + * + * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to update the content. + */ +export async function restoreContentVersion(client: Client, parameters: RestoreContentVersion): Promise { + const config: SendRequestOptions = { + url: `/wiki/rest/api/content/${parameters.id}/version`, + method: 'POST', + headers: { + 'X-Atlassian-Token': 'no-check', + }, + searchParams: { + expand: parameters.expand, + }, + body: { + operationKey: parameters.operationKey, + params: parameters.params, + }, + schema: VersionSchema, + }; + + return await client.sendRequest(config); +} + +/** + * Delete a historical version. This does not delete the changes made to the content in that version, rather the changes + * for the deleted version are rolled up into the next version. Note, you cannot delete the current version. + * + * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to update the content. + */ +export async function deleteContentVersion(client: Client, parameters: DeleteContentVersion): Promise { + const config: SendRequestOptions = { + url: `/wiki/rest/api/content/${parameters.id}/version/${parameters.versionNumber}`, + method: 'DELETE', + headers: { + 'X-Atlassian-Token': 'no-check', + }, + }; + + return await client.sendRequest(config); +} diff --git a/src/v1/api/contentWatches.ts b/src/v1/api/contentWatches.ts new file mode 100644 index 00000000..45177d0b --- /dev/null +++ b/src/v1/api/contentWatches.ts @@ -0,0 +1,319 @@ +import { WatchArraySchema, type WatchArray } from '../models/watchArray'; +import { SpaceWatchArraySchema, type SpaceWatchArray } from '../models/spaceWatchArray'; +import { UserWatchSchema, type UserWatch } from '../models/userWatch'; +import type { GetWatchesForPage } from '../parameters/getWatchesForPage'; +import type { GetWatchesForSpace } from '../parameters/getWatchesForSpace'; +import type { GetWatchersForSpace } from '../parameters/getWatchersForSpace'; +import type { GetContentWatchStatus } from '../parameters/getContentWatchStatus'; +import type { AddContentWatcher } from '../parameters/addContentWatcher'; +import type { RemoveContentWatcher } from '../parameters/removeContentWatcher'; +import type { IsWatchingLabel } from '../parameters/isWatchingLabel'; +import type { AddLabelWatcher } from '../parameters/addLabelWatcher'; +import type { RemoveLabelWatcher } from '../parameters/removeLabelWatcher'; +import type { IsWatchingSpace } from '../parameters/isWatchingSpace'; +import type { AddSpaceWatcher } from '../parameters/addSpaceWatcher'; +import type { RemoveSpaceWatch } from '../parameters/removeSpaceWatch'; +import type { Client, SendRequestOptions } from '#/core'; + +/** + * Returns the watches for a page. A user that watches a page will receive receive notifications when the page is + * updated. + * + * If you want to manage watches for a page, use the following `user` methods: + * + * - [Get content watch status for user](#api-user-watch-content-contentId-get) + * - [Add content watch](#api-user-watch-content-contentId-post) + * - [Remove content watch](#api-user-watch-content-contentId-delete) + * + * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to access the Confluence site ('Can + * use' global permission). + */ +export async function getWatchesForPage(client: Client, parameters: GetWatchesForPage): Promise { + const config: SendRequestOptions = { + url: `/wiki/rest/api/content/${parameters.id}/notification/child-created`, + method: 'GET', + searchParams: { + start: parameters.start, + limit: parameters.limit, + }, + schema: WatchArraySchema, + }; + + return await client.sendRequest(config); +} + +/** + * Returns all space watches for the space that the content is in. A user that watches a space will receive receive + * notifications when any content in the space is updated. + * + * If you want to manage watches for a space, use the following `user` methods: + * + * - [Get space watch status for user](#api-user-watch-space-spaceKey-get) + * - [Add space watch](#api-user-watch-space-spaceKey-post) + * - [Remove space watch](#api-user-watch-space-spaceKey-delete) + * + * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to access the Confluence site ('Can + * use' global permission). + */ +export async function getWatchesForSpace(client: Client, parameters: GetWatchesForSpace): Promise { + const config: SendRequestOptions = { + url: `/wiki/rest/api/content/${parameters.id}/notification/created`, + method: 'GET', + searchParams: { + start: parameters.start, + limit: parameters.limit, + }, + schema: SpaceWatchArraySchema, + }; + + return await client.sendRequest(config); +} + +/** Returns a list of watchers of a space */ +export async function getWatchersForSpace(client: Client, parameters: GetWatchersForSpace): Promise { + const config: SendRequestOptions = { + url: `/wiki/rest/api/space/${parameters.spaceKey}/watch`, + method: 'GET', + searchParams: { + start: parameters.start, + limit: parameters.limit, + }, + schema: SpaceWatchArraySchema, + }; + + return await client.sendRequest(config); +} + +/** + * Returns whether a user is watching a piece of content. Choose the user by doing one of the following: + * + * - Specify a user via a query parameter: Use the `accountId` to identify the user. + * - Do not specify a user: The currently logged-in user will be used. + * + * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'Confluence Administrator' global permission + * or 'Space Administrator' permission for the relevant space if specifying a user, otherwise permission to access the + * Confluence site ('Can use' global permission). + */ +export async function getContentWatchStatus(client: Client, parameters: GetContentWatchStatus): Promise { + const config: SendRequestOptions = { + url: `/wiki/rest/api/user/watch/content/${parameters.contentId}`, + method: 'GET', + searchParams: { + key: parameters.key, + username: parameters.username, + accountId: parameters.accountId, + }, + schema: UserWatchSchema, + }; + + return await client.sendRequest(config); +} + +/** + * Adds a user as a watcher to a piece of content. Choose the user by doing one of the following: + * + * - Specify a user via a query parameter: Use the `accountId` to identify the user. + * - Do not specify a user: The currently logged-in user will be used. + * + * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'Confluence Administrator' global permission + * or 'Space Administrator' permission for the relevant space if specifying a user, otherwise permission to access the + * Confluence site ('Can use' global permission). + */ +export async function addContentWatcher(client: Client, parameters: AddContentWatcher): Promise { + const config: SendRequestOptions = { + url: `/wiki/rest/api/user/watch/content/${parameters.contentId}`, + method: 'POST', + headers: { + 'X-Atlassian-Token': 'no-check', + }, + searchParams: { + key: parameters.key, + username: parameters.username, + accountId: parameters.accountId, + }, + }; + + return await client.sendRequest(config); +} + +/** + * Removes a user as a watcher from a piece of content. Choose the user by doing one of the following: + * + * - Specify a user via a query parameter: Use the `accountId` to identify the user. + * - Do not specify a user: The currently logged-in user will be used. + * + * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'Confluence Administrator' global permission + * or 'Space Administrator' permission for the relevant space if specifying a user, otherwise permission to access the + * Confluence site ('Can use' global permission). + */ +export async function removeContentWatcher(client: Client, parameters: RemoveContentWatcher): Promise { + const config: SendRequestOptions = { + url: `/wiki/rest/api/user/watch/content/${parameters.contentId}`, + method: 'DELETE', + headers: { + 'X-Atlassian-Token': 'no-check', + }, + searchParams: { + key: parameters.key, + username: parameters.username, + accountId: parameters.accountId, + }, + }; + + return await client.sendRequest(config); +} + +/** + * Returns whether a user is watching a label. Choose the user by doing one of the following: + * + * - Specify a user via a query parameter: Use the `accountId` to identify the user. + * - Do not specify a user: The currently logged-in user will be used. + * + * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'Confluence Administrator' global permission + * if specifying a user, otherwise permission to access the Confluence site ('Can use' global permission). + */ +export async function isWatchingLabel(client: Client, parameters: IsWatchingLabel): Promise { + const config: SendRequestOptions = { + url: `/wiki/rest/api/user/watch/label/${parameters.labelName}`, + method: 'GET', + searchParams: { + key: parameters.key, + username: parameters.username, + accountId: parameters.accountId, + }, + schema: UserWatchSchema, + }; + + return await client.sendRequest(config); +} + +/** + * Adds a user as a watcher to a label. Choose the user by doing one of the following: + * + * - Specify a user via a query parameter: Use the `accountId` to identify the user. + * - Do not specify a user: The currently logged-in user will be used. + * + * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'Confluence Administrator' global permission + * if specifying a user, otherwise permission to access the Confluence site ('Can use' global permission). + */ +export async function addLabelWatcher(client: Client, parameters: AddLabelWatcher): Promise { + const config: SendRequestOptions = { + url: `/wiki/rest/api/user/watch/label/${parameters.labelName}`, + method: 'POST', + headers: { + 'X-Atlassian-Token': 'no-check', + }, + searchParams: { + key: parameters.key, + username: parameters.username, + accountId: parameters.accountId, + }, + }; + + return await client.sendRequest(config); +} + +/** + * Removes a user as a watcher from a label. Choose the user by doing one of the following: + * + * - Specify a user via a query parameter: Use the `accountId` to identify the user. + * - Do not specify a user: The currently logged-in user will be used. + * + * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'Confluence Administrator' global permission + * if specifying a user, otherwise permission to access the Confluence site ('Can use' global permission). + */ +export async function removeLabelWatcher(client: Client, parameters: RemoveLabelWatcher): Promise { + const config: SendRequestOptions = { + url: `/wiki/rest/api/user/watch/label/${parameters.labelName}`, + method: 'DELETE', + headers: { + 'X-Atlassian-Token': 'no-check', + }, + searchParams: { + key: parameters.key, + username: parameters.username, + accountId: parameters.accountId, + }, + }; + + return await client.sendRequest(config); +} + +/** + * Returns whether a user is watching a space. Choose the user by doing one of the following: + * + * - Specify a user via a query parameter: Use the `accountId` to identify the user. + * - Do not specify a user: The currently logged-in user will be used. + * + * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'Confluence Administrator' global permission + * or 'Space Administrator' permission for the relevant space if specifying a user, otherwise permission to access the + * Confluence site ('Can use' global permission). + */ +export async function isWatchingSpace(client: Client, parameters: IsWatchingSpace): Promise { + const config: SendRequestOptions = { + url: `/wiki/rest/api/user/watch/space/${parameters.spaceKey}`, + method: 'GET', + searchParams: { + key: parameters.key, + username: parameters.username, + accountId: parameters.accountId, + }, + schema: UserWatchSchema, + }; + + return await client.sendRequest(config); +} + +/** + * Adds a user as a watcher to a space. Choose the user by doing one of the following: + * + * - Specify a user via a query parameter: Use the `accountId` to identify the user. + * - Do not specify a user: The currently logged-in user will be used. + * + * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'Confluence Administrator' global permission + * or 'Space Administrator' permission for the relevant space if specifying a user, otherwise permission to access the + * Confluence site ('Can use' global permission). + */ +export async function addSpaceWatcher(client: Client, parameters: AddSpaceWatcher): Promise { + const config: SendRequestOptions = { + url: `/wiki/rest/api/user/watch/space/${parameters.spaceKey}`, + method: 'POST', + headers: { + 'X-Atlassian-Token': 'no-check', + }, + searchParams: { + key: parameters.key, + username: parameters.username, + accountId: parameters.accountId, + }, + }; + + return await client.sendRequest(config); +} + +/** + * Removes a user as a watcher from a space. Choose the user by doing one of the following: + * + * - Specify a user via a query parameter: Use the `accountId` to identify the user. + * - Do not specify a user: The currently logged-in user will be used. + * + * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'Confluence Administrator' global permission + * or 'Space Administrator' permission for the relevant space if specifying a user, otherwise permission to access the + * Confluence site ('Can use' global permission). + */ +export async function removeSpaceWatch(client: Client, parameters: RemoveSpaceWatch): Promise { + const config: SendRequestOptions = { + url: `/wiki/rest/api/user/watch/space/${parameters.spaceKey}`, + method: 'DELETE', + headers: { + 'X-Atlassian-Token': 'no-check', + }, + searchParams: { + key: parameters.key, + username: parameters.username, + accountId: parameters.accountId, + }, + }; + + return await client.sendRequest(config); +} diff --git a/src/v1/api/dynamicModules.ts b/src/v1/api/dynamicModules.ts new file mode 100644 index 00000000..6f326b3e --- /dev/null +++ b/src/v1/api/dynamicModules.ts @@ -0,0 +1,56 @@ +import type { RegisterModules } from '../parameters/registerModules'; +import type { RemoveModules } from '../parameters/removeModules'; +import type { Client, SendRequestOptions } from '#/core'; + +/** + * Returns all modules registered dynamically by the calling app. + * + * **[Permissions](#permissions) required:** Only Connect apps can make this request. + */ +export async function getModules(client: Client): Promise { + const config: SendRequestOptions = { + url: '/wiki/rest/atlassian-connect/1/app/module/dynamic', + method: 'GET', + }; + + return await client.sendRequest(config); +} + +/** + * Registers a list of modules. For the list of modules that support dynamic registration, see [Dynamic + * modules](https://developer.atlassian.com/cloud/confluence/dynamic-modules/). + * + * **[Permissions](#permissions) required:** Only Connect apps can make this request. + */ +export async function registerModules(client: Client, parameters: RegisterModules): Promise { + const config: SendRequestOptions = { + url: '/wiki/rest/atlassian-connect/1/app/module/dynamic', + method: 'POST', + headers: { + 'X-Atlassian-Token': 'no-check', + }, + body: parameters.body, + }; + + return await client.sendRequest(config); +} + +/** + * Remove all or a list of modules registered by the calling app. + * + * **[Permissions](#permissions) required:** Only Connect apps can make this request. + */ +export async function removeModules(client: Client, parameters: RemoveModules): Promise { + const config: SendRequestOptions = { + url: '/wiki/rest/atlassian-connect/1/app/module/dynamic', + method: 'DELETE', + headers: { + 'X-Atlassian-Token': 'no-check', + }, + searchParams: { + moduleKey: parameters.moduleKey, + }, + }; + + return await client.sendRequest(config); +} diff --git a/src/v1/api/experimental.ts b/src/v1/api/experimental.ts new file mode 100644 index 00000000..76117483 --- /dev/null +++ b/src/v1/api/experimental.ts @@ -0,0 +1,102 @@ +import { LongTaskSchema, type LongTask } from '../models/longTask'; +import { LabelArraySchema, type LabelArray } from '../models/labelArray'; +import type { DeletePageTree } from '../parameters/deletePageTree'; +import type { GetLabelsForSpace } from '../parameters/getLabelsForSpace'; +import type { AddLabelsToSpace } from '../parameters/addLabelsToSpace'; +import type { DeleteLabelFromSpace } from '../parameters/deleteLabelFromSpace'; +import type { Client, SendRequestOptions } from '#/core'; + +/** + * Moves a pagetree rooted at a page to the space's trash: + * + * - If the content's type is `page` and its status is `current`, it will be trashed including all its descendants. + * - For every other combination of content type and status, this API is not supported. + * + * This API accepts the pageTree delete request and returns a task ID. The delete process happens asynchronously. + * + * Response example:

+ *  {
+ *       "id" : "1180606",
+ *       "links" : {
+ *            "status" : "/rest/api/longtask/1180606"
+ *       }
+ *  }
+ *  
+ * + * Use the `/longtask/` REST API to get the copy task status. + * + * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'Delete' permission for the space that the + * content is in. + */ +export async function deletePageTree(client: Client, parameters: DeletePageTree): Promise { + const config: SendRequestOptions = { + url: `/wiki/rest/api/content/${parameters.id}/pageTree`, + method: 'DELETE', + headers: { + 'X-Atlassian-Token': 'no-check', + }, + schema: LongTaskSchema, + }; + + return await client.sendRequest(config); +} + +/** + * Returns a list of labels associated with a space. Can provide a prefix as well as other filters to select different + * types of labels. + */ +export async function getLabelsForSpace(client: Client, parameters: GetLabelsForSpace): Promise { + const config: SendRequestOptions = { + url: `/wiki/rest/api/space/${parameters.spaceKey}/label`, + method: 'GET', + searchParams: { + prefix: parameters.prefix, + start: parameters.start, + limit: parameters.limit, + }, + schema: LabelArraySchema, + }; + + return await client.sendRequest(config); +} + +/** + * Adds labels to a piece of content. Does not modify the existing labels. + * + * Notes: + * + * - Labels can also be added when creating content ([Create content](#api-content-post)). + * - Labels can be updated when updating content ([Update content](#api-content-id-put)). This will delete the existing + * labels and replace them with the labels in the request. + * + * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to update the content. + */ +export async function addLabelsToSpace(client: Client, parameters: AddLabelsToSpace): Promise { + const config: SendRequestOptions = { + url: `/wiki/rest/api/space/${parameters.spaceKey}/label`, + method: 'POST', + headers: { + 'X-Atlassian-Token': 'no-check', + }, + body: parameters.body, + schema: LabelArraySchema, + }; + + return await client.sendRequest(config); +} + +export async function deleteLabelFromSpace(client: Client, parameters: DeleteLabelFromSpace): Promise { + const config: SendRequestOptions = { + url: `/wiki/rest/api/space/${parameters.spaceKey}/label`, + method: 'DELETE', + headers: { + 'X-Atlassian-Token': 'no-check', + }, + searchParams: { + name: parameters.name, + prefix: parameters.prefix, + }, + }; + + return await client.sendRequest(config); +} diff --git a/src/v1/api/group.ts b/src/v1/api/group.ts new file mode 100644 index 00000000..611c0fe2 --- /dev/null +++ b/src/v1/api/group.ts @@ -0,0 +1,186 @@ +import { GroupArrayWithLinksSchema, type GroupArrayWithLinks } from '../models/groupArrayWithLinks'; +import { GroupSchema, type Group } from '../models/group'; +import { UserArraySchema, type UserArray } from '../models/userArray'; +import type { GetGroups } from '../parameters/getGroups'; +import type { CreateGroup } from '../parameters/createGroup'; +import type { GetGroupByGroupId } from '../parameters/getGroupByGroupId'; +import type { RemoveGroupById } from '../parameters/removeGroupById'; +import type { SearchGroups } from '../parameters/searchGroups'; +import type { GetGroupMembersByGroupId } from '../parameters/getGroupMembersByGroupId'; +import type { AddUserToGroupByGroupId } from '../parameters/addUserToGroupByGroupId'; +import type { RemoveMemberFromGroupByGroupId } from '../parameters/removeMemberFromGroupByGroupId'; +import type { Client, SendRequestOptions } from '#/core'; + +/** + * Returns all user groups. The returned groups are ordered alphabetically in ascending order by group name. + * + * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to access the Confluence site ('Can + * use' global permission). + */ +export async function getGroups(client: Client, parameters?: GetGroups): Promise { + const config: SendRequestOptions = { + url: '/wiki/rest/api/group', + method: 'GET', + searchParams: { + start: parameters?.start, + limit: parameters?.limit, + accessType: parameters?.accessType, + }, + schema: GroupArrayWithLinksSchema, + }; + + return await client.sendRequest(config); +} + +/** + * Creates a new user group. + * + * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: User must be a site admin. + */ +export async function createGroup(client: Client, parameters: CreateGroup): Promise { + const config: SendRequestOptions = { + url: '/wiki/rest/api/group', + method: 'POST', + headers: { + 'X-Atlassian-Token': 'no-check', + }, + body: { + name: parameters.name, + }, + schema: GroupSchema, + }; + + return await client.sendRequest(config); +} + +/** + * Returns a user group for a given group id. + * + * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to access the Confluence site ('Can + * use' global permission). + */ +export async function getGroupByGroupId(client: Client, parameters: GetGroupByGroupId): Promise { + const config: SendRequestOptions = { + url: '/wiki/rest/api/group/by-id', + method: 'GET', + searchParams: { + id: parameters.id, + }, + schema: GroupSchema, + }; + + return await client.sendRequest(config); +} + +/** + * Delete user group. + * + * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: User must be a site admin. + */ +export async function removeGroupById(client: Client, parameters: RemoveGroupById): Promise { + const config: SendRequestOptions = { + url: '/wiki/rest/api/group/by-id', + method: 'DELETE', + headers: { + 'X-Atlassian-Token': 'no-check', + }, + searchParams: { + id: parameters.id, + }, + }; + + return await client.sendRequest(config); +} + +/** Get search results of groups by partial query provided. */ +export async function searchGroups(client: Client, parameters: SearchGroups): Promise { + const config: SendRequestOptions = { + url: '/wiki/rest/api/group/picker', + method: 'GET', + searchParams: { + query: parameters.query, + start: parameters.start, + limit: parameters.limit, + shouldReturnTotalSize: parameters.shouldReturnTotalSize, + }, + schema: GroupArrayWithLinksSchema, + }; + + return await client.sendRequest(config); +} + +/** + * Returns the users that are members of a group. + * + * Use updated Get group API + * + * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to access the Confluence site ('Can + * use' global permission). + */ +export async function getGroupMembersByGroupId( + client: Client, + parameters: GetGroupMembersByGroupId, +): Promise { + const config: SendRequestOptions = { + url: `/wiki/rest/api/group/${parameters.groupId}/membersByGroupId`, + method: 'GET', + searchParams: { + start: parameters.start, + limit: parameters.limit, + shouldReturnTotalSize: parameters.shouldReturnTotalSize, + expand: parameters.expand, + }, + schema: UserArraySchema, + }; + + return await client.sendRequest(config); +} + +/** + * Adds a user as a member in a group represented by its groupId + * + * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: User must be a site admin. + */ +export async function addUserToGroupByGroupId(client: Client, parameters: AddUserToGroupByGroupId): Promise { + const config: SendRequestOptions = { + url: '/wiki/rest/api/group/userByGroupId', + method: 'POST', + headers: { + 'X-Atlassian-Token': 'no-check', + }, + searchParams: { + groupId: parameters.groupId, + }, + body: { + accountId: parameters.accountId, + }, + }; + + return await client.sendRequest(config); +} + +/** + * Remove user as a member from a group. + * + * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: User must be a site admin. + */ +export async function removeMemberFromGroupByGroupId( + client: Client, + parameters: RemoveMemberFromGroupByGroupId, +): Promise { + const config: SendRequestOptions = { + url: '/wiki/rest/api/group/userByGroupId', + method: 'DELETE', + headers: { + 'X-Atlassian-Token': 'no-check', + }, + searchParams: { + groupId: parameters.groupId, + accountId: parameters.accountId, + key: parameters.key, + username: parameters.username, + }, + }; + + return await client.sendRequest(config); +} diff --git a/src/v1/api/index.ts b/src/v1/api/index.ts new file mode 100644 index 00000000..47145653 --- /dev/null +++ b/src/v1/api/index.ts @@ -0,0 +1,55 @@ +export * from './analytics'; + +export * from './audit'; + +export * from './content'; + +export * from './contentAttachments'; + +export * from './contentBody'; + +export * from './contentChildrenAndDescendants'; + +export * from './contentLabels'; + +export * from './contentMacroBody'; + +export * from './contentPermissions'; + +export * from './contentRestrictions'; + +export * from './contentStates'; + +export * from './contentVersions'; + +export * from './contentWatches'; + +export * from './dynamicModules'; + +export * from './experimental'; + +export * from './group'; + +export * from './labelInfo'; + +export * from './longRunningTask'; + +export * from './relation'; + +export * from './search'; + +export * from './settings'; + +export * from './space'; + +export * from './spacePermissions'; + +export * from './spaceSettings'; + +export * from './template'; + +export * from './themes'; + +export * from './userProperties'; + +export * from './users'; diff --git a/src/v1/api/labelInfo.ts b/src/v1/api/labelInfo.ts new file mode 100644 index 00000000..7493deac --- /dev/null +++ b/src/v1/api/labelInfo.ts @@ -0,0 +1,25 @@ +import { LabelDetailsSchema, type LabelDetails } from '../models/labelDetails'; +import type { GetAllLabelContent } from '../parameters/getAllLabelContent'; +import type { Client, SendRequestOptions } from '#/core'; + +/** + * Returns label information and a list of contents associated with the label. + * + * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to access the Confluence site ('Can + * use' global permission). Only contents that the user is permitted to view is returned. + */ +export async function getAllLabelContent(client: Client, parameters: GetAllLabelContent): Promise { + const config: SendRequestOptions = { + url: '/wiki/rest/api/label', + method: 'GET', + searchParams: { + name: parameters.name, + type: parameters.type, + start: parameters.start, + limit: parameters.limit, + }, + schema: LabelDetailsSchema, + }; + + return await client.sendRequest(config); +} diff --git a/src/v1/api/longRunningTask.ts b/src/v1/api/longRunningTask.ts new file mode 100644 index 00000000..886d5ea2 --- /dev/null +++ b/src/v1/api/longRunningTask.ts @@ -0,0 +1,44 @@ +import { LongTaskStatusArraySchema, type LongTaskStatusArray } from '../models/longTaskStatusArray'; +import { LongTaskStatusWithLinksSchema, type LongTaskStatusWithLinks } from '../models/longTaskStatusWithLinks'; +import type { GetTasks } from '../parameters/getTasks'; +import type { GetTask } from '../parameters/getTask'; +import type { Client, SendRequestOptions } from '#/core'; + +/** + * Returns information about all active long-running tasks (e.g. space export), such as how long each task has been + * running and the percentage of each task that has completed. + * + * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to access the Confluence site ('Can + * use' global permission). + */ +export async function getTasks(client: Client, parameters?: GetTasks): Promise { + const config: SendRequestOptions = { + url: '/wiki/rest/api/longtask', + method: 'GET', + searchParams: { + key: parameters?.key, + start: parameters?.start, + limit: parameters?.limit, + }, + schema: LongTaskStatusArraySchema, + }; + + return await client.sendRequest(config); +} + +/** + * Returns information about an active long-running task (e.g. space export), such as how long it has been running and + * the percentage of the task that has completed. + * + * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to access the Confluence site ('Can + * use' global permission). + */ +export async function getTask(client: Client, parameters: GetTask): Promise { + const config: SendRequestOptions = { + url: `/wiki/rest/api/longtask/${parameters.id}`, + method: 'GET', + schema: LongTaskStatusWithLinksSchema, + }; + + return await client.sendRequest(config); +} diff --git a/src/v1/api/relation.ts b/src/v1/api/relation.ts new file mode 100644 index 00000000..a13299e1 --- /dev/null +++ b/src/v1/api/relation.ts @@ -0,0 +1,148 @@ +import { RelationArraySchema, type RelationArray } from '../models/relationArray'; +import { RelationSchema, type Relation } from '../models/relation'; +import type { FindTargetFromSource } from '../parameters/findTargetFromSource'; +import type { GetRelationship } from '../parameters/getRelationship'; +import type { CreateRelationship } from '../parameters/createRelationship'; +import type { DeleteRelationship } from '../parameters/deleteRelationship'; +import type { FindSourcesForTarget } from '../parameters/findSourcesForTarget'; +import type { Client, SendRequestOptions } from '#/core'; + +/** + * Returns all target entities that have a particular relationship to the source entity. Note, relationships are one + * way. + * + * For example, the following method finds all content that the current user has an 'ignore' relationship with: `GET + * /wiki/rest/api/relation/ignore/from/user/current/to/content` Note, 'ignore' is an example custom relationship type. + * + * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to view both the target entity and + * source entity. + */ +export async function findTargetFromSource(client: Client, parameters: FindTargetFromSource): Promise { + const config: SendRequestOptions = { + url: `/wiki/rest/api/relation/${parameters.relationName}/from/${parameters.sourceType}/${parameters.sourceKey}/to/${parameters.targetType}`, + method: 'GET', + searchParams: { + sourceStatus: parameters.sourceStatus, + targetStatus: parameters.targetStatus, + sourceVersion: parameters.sourceVersion, + targetVersion: parameters.targetVersion, + expand: parameters.expand, + start: parameters.start, + limit: parameters.limit, + }, + schema: RelationArraySchema, + }; + + return await client.sendRequest(config); +} + +/** + * Find whether a particular type of relationship exists from a source entity to a target entity. Note, relationships + * are one way. + * + * For example, you can use this method to find whether the current user has selected a particular page as a favorite + * (i.e. 'save for later'): `GET /wiki/rest/api/relation/favourite/from/user/current/to/content/123` + * + * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to view both the target entity and + * source entity. + */ +export async function getRelationship(client: Client, parameters: GetRelationship): Promise { + const config: SendRequestOptions = { + url: `/wiki/rest/api/relation/${parameters.relationName}/from/${parameters.sourceType}/${parameters.sourceKey}/to/${parameters.targetType}/${parameters.targetKey}`, + method: 'GET', + searchParams: { + sourceStatus: parameters.sourceStatus, + targetStatus: parameters.targetStatus, + sourceVersion: parameters.sourceVersion, + targetVersion: parameters.targetVersion, + expand: parameters.expand, + }, + schema: RelationSchema, + }; + + return await client.sendRequest(config); +} + +/** + * Creates a relationship between two entities (user, space, content). The 'favourite' relationship is supported by + * default, but you can use this method to create any type of relationship between two entities. + * + * For example, the following method creates a 'sibling' relationship between two pieces of content: `PUT + * /wiki/rest/api/relation/sibling/from/content/123/to/content/456` + * + * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to access the Confluence site ('Can + * use' global permission). + */ +export async function createRelationship(client: Client, parameters: CreateRelationship): Promise { + const config: SendRequestOptions = { + url: `/wiki/rest/api/relation/${parameters.relationName}/from/${parameters.sourceType}/${parameters.sourceKey}/to/${parameters.targetType}/${parameters.targetKey}`, + method: 'PUT', + headers: { + 'X-Atlassian-Token': 'no-check', + }, + searchParams: { + sourceStatus: parameters.sourceStatus, + targetStatus: parameters.targetStatus, + sourceVersion: parameters.sourceVersion, + targetVersion: parameters.targetVersion, + }, + schema: RelationSchema, + }; + + return await client.sendRequest(config); +} + +/** + * Deletes a relationship between two entities (user, space, content). + * + * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to access the Confluence site ('Can + * use' global permission). For favourite relationships, the current user can only delete their own favourite + * relationships. A space administrator can delete favourite relationships for any user. + */ +export async function deleteRelationship(client: Client, parameters: DeleteRelationship): Promise { + const config: SendRequestOptions = { + url: `/wiki/rest/api/relation/${parameters.relationName}/from/${parameters.sourceType}/${parameters.sourceKey}/to/${parameters.targetType}/${parameters.targetKey}`, + method: 'DELETE', + headers: { + 'X-Atlassian-Token': 'no-check', + }, + searchParams: { + sourceStatus: parameters.sourceStatus, + targetStatus: parameters.targetStatus, + sourceVersion: parameters.sourceVersion, + targetVersion: parameters.targetVersion, + }, + }; + + return await client.sendRequest(config); +} + +/** + * Returns all target entities that have a particular relationship to the source entity. Note, relationships are one + * way. + * + * For example, the following method finds all users that have a 'collaborator' relationship to a piece of content with + * an ID of '1234': `GET /wiki/rest/api/relation/collaborator/to/content/1234/from/user` Note, 'collaborator' is an + * example custom relationship type. + * + * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to view both the target entity and + * source entity. + */ +export async function findSourcesForTarget(client: Client, parameters: FindSourcesForTarget): Promise { + const config: SendRequestOptions = { + url: `/wiki/rest/api/relation/${parameters.relationName}/to/${parameters.targetType}/${parameters.targetKey}/from/${parameters.sourceType}`, + method: 'GET', + searchParams: { + sourceStatus: parameters.sourceStatus, + targetStatus: parameters.targetStatus, + sourceVersion: parameters.sourceVersion, + targetVersion: parameters.targetVersion, + expand: parameters.expand, + start: parameters.start, + limit: parameters.limit, + }, + schema: RelationArraySchema, + }; + + return await client.sendRequest(config); +} diff --git a/src/v1/api/search.ts b/src/v1/api/search.ts new file mode 100644 index 00000000..bd7a47a5 --- /dev/null +++ b/src/v1/api/search.ts @@ -0,0 +1,107 @@ +import { + SearchPageResponseSearchResultSchema, + type SearchPageResponseSearchResult, +} from '../models/searchPageResponseSearchResult'; +import type { SearchByCQL } from '../parameters/searchByCQL'; +import type { SearchUser } from '../parameters/searchUser'; +import type { Client, SendRequestOptions } from '#/core'; + +/** + * Searches for content using the [Confluence Query Language + * (CQL)](https://developer.atlassian.com/cloud/confluence/advanced-searching-using-cql/). + * + * **Note that CQL input queries submitted through the `/wiki/rest/api/search` endpoint no longer support user-specific + * fields like `user`, `user.fullname`, `user.accountid`, and `user.userkey`.** See this [deprecation + * notice](https://developer.atlassian.com/cloud/confluence/deprecation-notice-search-api/) for more details. + * + * Example initial call: + * + * /wiki/rest/api/search?cql=type=page&limit=25 + * + * Example response: + * + * { + * "results": [ + * { ... }, + * { ... }, + * ... + * { ... } + * ], + * "limit": 25, + * "size": 25, + * ... + * "_links": { + * "base": "", + * "context": "", + * "next": "/rest/api/search?cql=type=page&limit=25&cursor=raNDoMsTRiNg", + * "self": "" + * } + * } + * + * When additional results are available, returns `next` and `prev` URLs to retrieve them in subsequent calls. The URLs + * each contain a cursor that points to the appropriate set of results. Use `limit` to specify the number of results + * returned in each call. + * + * Example subsequent call (taken from example response): + * + * /wiki/rest/api/search?cql=type=page&limit=25&cursor=raNDoMsTRiNg + * + * The response to this will have a `prev` URL similar to the `next` in the example response. + * + * If the expand query parameter is used with the `body.export_view` and/or `body.styled_view` properties, then the + * query limit parameter will be restricted to a maximum value of 25. + * + * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to view the entities. Note, only + * entities that the user has permission to view will be returned. + */ +export async function searchByCQL(client: Client, parameters: SearchByCQL): Promise { + const config: SendRequestOptions = { + url: '/wiki/rest/api/search', + method: 'GET', + searchParams: { + cql: parameters.cql, + cqlcontext: parameters.cqlcontext, + cursor: parameters.cursor, + next: parameters.next, + prev: parameters.prev, + limit: parameters.limit, + start: parameters.start, + includeArchivedSpaces: parameters.includeArchivedSpaces, + excludeCurrentSpaces: parameters.excludeCurrentSpaces, + excerpt: parameters.excerpt, + sitePermissionTypeFilter: parameters.sitePermissionTypeFilter, + _: parameters._, + expand: parameters.expand, + }, + schema: SearchPageResponseSearchResultSchema, + }; + + return await client.sendRequest(config); +} + +/** + * Searches for users using user-specific queries from the [Confluence Query Language + * (CQL)](https://developer.atlassian.com/cloud/confluence/advanced-searching-using-cql/). + * + * Note that CQL input queries submitted through the `/wiki/rest/api/search/user` endpoint only support user-specific + * fields like `user`, `user.fullname`, `user.accountid`, and `user.userkey`. + * + * Note that some user fields may be set to null depending on the user's privacy settings. These are: email, + * profilePicture, displayName, and timeZone. + */ +export async function searchUser(client: Client, parameters: SearchUser): Promise { + const config: SendRequestOptions = { + url: '/wiki/rest/api/search/user', + method: 'GET', + searchParams: { + cql: parameters.cql, + start: parameters.start, + limit: parameters.limit, + expand: parameters.expand, + sitePermissionTypeFilter: parameters.sitePermissionTypeFilter, + }, + schema: SearchPageResponseSearchResultSchema, + }; + + return await client.sendRequest(config); +} diff --git a/src/v1/api/settings.ts b/src/v1/api/settings.ts new file mode 100644 index 00000000..92c3806c --- /dev/null +++ b/src/v1/api/settings.ts @@ -0,0 +1,134 @@ +import { LookAndFeelSettingsSchema, type LookAndFeelSettings } from '../models/lookAndFeelSettings'; +import { LookAndFeelSelectionSchema, type LookAndFeelSelection } from '../models/lookAndFeelSelection'; +import { LookAndFeelWithLinksSchema, type LookAndFeelWithLinks } from '../models/lookAndFeelWithLinks'; +import { SystemInfoEntitySchema, type SystemInfoEntity } from '../models/systemInfoEntity'; +import type { GetLookAndFeelSettings } from '../parameters/getLookAndFeelSettings'; +import type { UpdateLookAndFeel } from '../parameters/updateLookAndFeel'; +import type { UpdateLookAndFeelSettings } from '../parameters/updateLookAndFeelSettings'; +import type { ResetLookAndFeelSettings } from '../parameters/resetLookAndFeelSettings'; +import type { Client, SendRequestOptions } from '#/core'; + +/** + * Returns the look and feel settings for the site or a single space. This includes attributes such as the color scheme, + * padding, and border radius. + * + * The look and feel settings for a space can be inherited from the global look and feel settings or provided by a + * theme. + * + * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: None + */ +export async function getLookAndFeelSettings( + client: Client, + parameters?: GetLookAndFeelSettings, +): Promise { + const config: SendRequestOptions = { + url: '/wiki/rest/api/settings/lookandfeel', + method: 'GET', + searchParams: { + spaceKey: parameters?.spaceKey, + }, + schema: LookAndFeelSettingsSchema, + }; + + return await client.sendRequest(config); +} + +/** + * Sets the look and feel settings to the default (global) settings, the custom settings, or the current theme's + * settings for a space. The custom and theme settings can only be selected if there is already a theme set for a space. + * Note, the default space settings are inherited from the current global settings. + * + * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'Admin' permission for the space. + */ +export async function updateLookAndFeel(client: Client, parameters: UpdateLookAndFeel): Promise { + const config: SendRequestOptions = { + url: '/wiki/rest/api/settings/lookandfeel', + method: 'PUT', + headers: { + 'X-Atlassian-Token': 'no-check', + }, + body: { + spaceKey: parameters.spaceKey, + lookAndFeelType: parameters.lookAndFeelType, + }, + schema: LookAndFeelSelectionSchema, + }; + + return await client.sendRequest(config); +} + +/** + * Updates the look and feel settings for the site or for a single space. If custom settings exist, they are updated. If + * no custom settings exist, then a set of custom settings is created. + * + * Note, if a theme is selected for a space, the space look and feel settings are provided by the theme and cannot be + * overridden. + * + * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'Admin' permission for the space. + */ +export async function updateLookAndFeelSettings( + client: Client, + parameters: UpdateLookAndFeelSettings, +): Promise { + const config: SendRequestOptions = { + url: '/wiki/rest/api/settings/lookandfeel/custom', + method: 'POST', + headers: { + 'X-Atlassian-Token': 'no-check', + }, + searchParams: { + spaceKey: parameters.spaceKey, + }, + body: { + headings: parameters.headings, + links: parameters.links, + menus: parameters.menus, + header: parameters.header, + horizontalHeader: parameters.horizontalHeader, + content: parameters.content, + bordersAndDividers: parameters.bordersAndDividers, + spaceReference: parameters.spaceReference, + }, + schema: LookAndFeelWithLinksSchema, + }; + + return await client.sendRequest(config); +} + +/** + * Resets the custom look and feel settings for the site or a single space. This changes the values of the custom + * settings to be the same as the default settings. It does not change which settings (default or custom) are selected. + * Note, the default space settings are inherited from the current global settings. + * + * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'Admin' permission for the space. + */ +export async function resetLookAndFeelSettings(client: Client, parameters: ResetLookAndFeelSettings): Promise { + const config: SendRequestOptions = { + url: '/wiki/rest/api/settings/lookandfeel/custom', + method: 'DELETE', + headers: { + 'X-Atlassian-Token': 'no-check', + }, + searchParams: { + spaceKey: parameters.spaceKey, + }, + }; + + return await client.sendRequest(config); +} + +/** + * Returns the system information for the Confluence Cloud tenant. This information is used by Atlassian. + * + * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to access the Confluence site ('Can + * use' global permission). + */ +export async function getSystemInfo(client: Client): Promise { + const config: SendRequestOptions = { + url: '/wiki/rest/api/settings/systemInfo', + method: 'GET', + schema: SystemInfoEntitySchema, + }; + + return await client.sendRequest(config); +} diff --git a/src/v1/api/space.ts b/src/v1/api/space.ts new file mode 100644 index 00000000..139b1587 --- /dev/null +++ b/src/v1/api/space.ts @@ -0,0 +1,107 @@ +import { SpaceSchema, type Space } from '../models/space'; +import { LongTaskSchema, type LongTask } from '../models/longTask'; +import type { CreateSpace } from '../parameters/createSpace'; +import type { CreatePrivateSpace } from '../parameters/createPrivateSpace'; +import type { UpdateSpace } from '../parameters/updateSpace'; +import type { DeleteSpace } from '../parameters/deleteSpace'; +import type { Client, SendRequestOptions } from '#/core'; + +/** + * Creates a new space. Note, currently you cannot set space labels when creating a space. + * + * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'Create Space(s)' global permission. + */ +export async function createSpace(client: Client, parameters: CreateSpace): Promise { + const config: SendRequestOptions = { + url: '/wiki/rest/api/space', + method: 'POST', + headers: { + 'X-Atlassian-Token': 'no-check', + }, + body: { + name: parameters.name, + key: parameters.key, + alias: parameters.alias, + description: parameters.description, + permissions: parameters.permissions, + }, + schema: SpaceSchema, + }; + + return await client.sendRequest(config); +} + +/** + * Creates a new space that is only visible to the creator. This method is the same as the [Create + * space](#api-space-post) method with permissions set to the current user only. Note, currently you cannot set space + * labels when creating a space. + * + * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'Create Space(s)' global permission. + */ +export async function createPrivateSpace(client: Client, parameters: CreatePrivateSpace): Promise { + const config: SendRequestOptions = { + url: '/wiki/rest/api/space/_private', + method: 'POST', + headers: { + 'X-Atlassian-Token': 'no-check', + }, + body: { + name: parameters.name, + key: parameters.key, + alias: parameters.alias, + description: parameters.description, + permissions: parameters.permissions, + }, + schema: SpaceSchema, + }; + + return await client.sendRequest(config); +} + +/** + * Updates the name, description, or homepage of a space. + * + * - For security reasons, permissions cannot be updated via the API and must be changed via the user interface instead. + * - Currently you cannot set space labels when updating a space. + * + * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'Admin' permission for the space. + */ +export async function updateSpace(client: Client, parameters: UpdateSpace): Promise { + const config: SendRequestOptions = { + url: `/wiki/rest/api/space/${parameters.spaceKey}`, + method: 'PUT', + headers: { + 'X-Atlassian-Token': 'no-check', + }, + body: { + name: parameters.name, + description: parameters.description, + homepage: parameters.homepage, + type: parameters.type, + status: parameters.status, + }, + schema: SpaceSchema, + }; + + return await client.sendRequest(config); +} + +/** + * Permanently deletes a space without sending it to the trash. Note, the space will be deleted in a long running task. + * Therefore, the space may not be deleted yet when this method has returned. Clients should poll the status link that + * is returned in the response until the task completes. + * + * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'Admin' permission for the space. + */ +export async function deleteSpace(client: Client, parameters: DeleteSpace): Promise { + const config: SendRequestOptions = { + url: `/wiki/rest/api/space/${parameters.spaceKey}`, + method: 'DELETE', + headers: { + 'X-Atlassian-Token': 'no-check', + }, + schema: LongTaskSchema, + }; + + return await client.sendRequest(config); +} diff --git a/src/v1/api/spacePermissions.ts b/src/v1/api/spacePermissions.ts new file mode 100644 index 00000000..c93b5b97 --- /dev/null +++ b/src/v1/api/spacePermissions.ts @@ -0,0 +1,83 @@ +import { SpacePermissionV2Schema, type SpacePermissionV2 } from '../models/spacePermissionV2'; +import type { AddPermissionToSpace } from '../parameters/addPermissionToSpace'; +import type { AddCustomContentPermissions } from '../parameters/addCustomContentPermissions'; +import type { RemovePermission } from '../parameters/removePermission'; +import type { Client, SendRequestOptions } from '#/core'; + +/** + * Adds new permission to space. + * + * If the permission to be added is a group permission, the group can be identified by its group name or group id. + * + * Note: Apps cannot access this REST resource - including when utilizing user impersonation. + * + * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'Admin' permission for the space. + */ +export async function addPermissionToSpace( + client: Client, + parameters: AddPermissionToSpace, +): Promise { + const config: SendRequestOptions = { + url: `/wiki/rest/api/space/${parameters.spaceKey}/permission`, + method: 'POST', + headers: { + 'X-Atlassian-Token': 'no-check', + }, + body: { + subject: parameters.subject, + operation: parameters.operation, + _links: parameters._links, + }, + schema: SpacePermissionV2Schema, + }; + + return await client.sendRequest(config); +} + +/** + * Adds new custom content permission to space. + * + * If the permission to be added is a group permission, the group can be identified by its group name or group id. + * + * Note: Only apps can access this REST resource and only make changes to the respective app permissions. + * + * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'Admin' permission for the space. + */ +export async function addCustomContentPermissions( + client: Client, + parameters: AddCustomContentPermissions, +): Promise { + const config: SendRequestOptions = { + url: `/wiki/rest/api/space/${parameters.spaceKey}/permission/custom-content`, + method: 'POST', + headers: { + 'X-Atlassian-Token': 'no-check', + }, + body: { + subject: parameters.subject, + operations: parameters.operations, + }, + }; + + return await client.sendRequest(config); +} + +/** + * Removes a space permission. Note that removing Read Space permission for a user or group will remove all the space + * permissions for that user or group. + * + * Note: Apps cannot access this REST resource - including when utilizing user impersonation. + * + * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'Admin' permission for the space. + */ +export async function removePermission(client: Client, parameters: RemovePermission): Promise { + const config: SendRequestOptions = { + url: `/wiki/rest/api/space/${parameters.spaceKey}/permission/${parameters.id}`, + method: 'DELETE', + headers: { + 'X-Atlassian-Token': 'no-check', + }, + }; + + return await client.sendRequest(config); +} diff --git a/src/v1/api/spaceSettings.ts b/src/v1/api/spaceSettings.ts new file mode 100644 index 00000000..da616a39 --- /dev/null +++ b/src/v1/api/spaceSettings.ts @@ -0,0 +1,41 @@ +import { SpaceSettingsSchema, type SpaceSettings } from '../models/spaceSettings'; +import type { GetSpaceSettings } from '../parameters/getSpaceSettings'; +import type { UpdateSpaceSettings } from '../parameters/updateSpaceSettings'; +import type { Client, SendRequestOptions } from '#/core'; + +/** + * Returns the settings of a space. + * + * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'View' permission for the space. + */ +export async function getSpaceSettings(client: Client, parameters: GetSpaceSettings): Promise { + const config: SendRequestOptions = { + url: `/wiki/rest/api/space/${parameters.spaceKey}/settings`, + method: 'GET', + schema: SpaceSettingsSchema, + }; + + return await client.sendRequest(config); +} + +/** + * Updates the settings for a space. + * + * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'Admin' permission for the space. + */ +export async function updateSpaceSettings(client: Client, parameters: UpdateSpaceSettings): Promise { + const config: SendRequestOptions = { + url: `/wiki/rest/api/space/${parameters.spaceKey}/settings`, + method: 'PUT', + headers: { + 'X-Atlassian-Token': 'no-check', + }, + body: { + routeOverrideEnabled: parameters.routeOverrideEnabled, + contentMode: parameters.contentMode, + }, + schema: SpaceSettingsSchema, + }; + + return await client.sendRequest(config); +} diff --git a/src/v1/api/template.ts b/src/v1/api/template.ts new file mode 100644 index 00000000..842f7dd1 --- /dev/null +++ b/src/v1/api/template.ts @@ -0,0 +1,173 @@ +import { ContentTemplateSchema, type ContentTemplate } from '../models/contentTemplate'; +import { BlueprintTemplateArraySchema, type BlueprintTemplateArray } from '../models/blueprintTemplateArray'; +import { ContentTemplateArraySchema, type ContentTemplateArray } from '../models/contentTemplateArray'; +import type { CreateContentTemplate } from '../parameters/createContentTemplate'; +import type { UpdateContentTemplate } from '../parameters/updateContentTemplate'; +import type { GetBlueprintTemplates } from '../parameters/getBlueprintTemplates'; +import type { GetContentTemplates } from '../parameters/getContentTemplates'; +import type { GetContentTemplate } from '../parameters/getContentTemplate'; +import type { RemoveTemplate } from '../parameters/removeTemplate'; +import type { Client, SendRequestOptions } from '#/core'; + +/** + * Creates a new content template. Note, blueprint templates cannot be created via the REST API. + * + * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'Admin' permission for the space to create a + * space template or 'Confluence Administrator' global permission to create a global template. + */ +export async function createContentTemplate( + client: Client, + parameters: CreateContentTemplate, +): Promise { + const config: SendRequestOptions = { + url: '/wiki/rest/api/template', + method: 'POST', + headers: { + 'X-Atlassian-Token': 'no-check', + }, + body: { + name: parameters.name, + templateType: parameters.templateType, + body: parameters.body, + description: parameters.description, + labels: parameters.labels, + space: parameters.space, + }, + schema: ContentTemplateSchema, + }; + + return await client.sendRequest(config); +} + +/** + * Updates a content template. Note, blueprint templates cannot be updated via the REST API. + * + * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'Admin' permission for the space to update a + * space template or 'Confluence Administrator' global permission to update a global template. + */ +export async function updateContentTemplate( + client: Client, + parameters: UpdateContentTemplate, +): Promise { + const config: SendRequestOptions = { + url: '/wiki/rest/api/template', + method: 'PUT', + headers: { + 'X-Atlassian-Token': 'no-check', + }, + body: { + templateId: parameters.templateId, + name: parameters.name, + templateType: parameters.templateType, + body: parameters.body, + description: parameters.description, + labels: parameters.labels, + space: parameters.space, + }, + schema: ContentTemplateSchema, + }; + + return await client.sendRequest(config); +} + +/** + * Returns all templates provided by blueprints. Use this method to retrieve all global blueprint templates or all + * blueprint templates in a space. + * + * Note, all global blueprints are inherited by each space. Space blueprints can be customised without affecting the + * global blueprints. + * + * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'View' permission for the space to view + * blueprints for the space and permission to access the Confluence site ('Can use' global permission) to view global + * blueprints. + */ +export async function getBlueprintTemplates( + client: Client, + parameters?: GetBlueprintTemplates, +): Promise { + const config: SendRequestOptions = { + url: '/wiki/rest/api/template/blueprint', + method: 'GET', + searchParams: { + spaceKey: parameters?.spaceKey, + start: parameters?.start, + limit: parameters?.limit, + expand: parameters?.expand, + }, + schema: BlueprintTemplateArraySchema, + }; + + return await client.sendRequest(config); +} + +/** + * Returns all content templates. Use this method to retrieve all global content templates or all content templates in a + * space. + * + * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'View' permission for the space to view space + * templates and permission to access the Confluence site ('Can use' global permission) to view global templates. + */ +export async function getContentTemplates( + client: Client, + parameters?: GetContentTemplates, +): Promise { + const config: SendRequestOptions = { + url: '/wiki/rest/api/template/page', + method: 'GET', + searchParams: { + spaceKey: parameters?.spaceKey, + start: parameters?.start, + limit: parameters?.limit, + expand: parameters?.expand, + }, + schema: ContentTemplateArraySchema, + }; + + return await client.sendRequest(config); +} + +/** + * Returns a content template. This includes information about template, like the name, the space or blueprint that the + * template is in, the body of the template, and more. + * + * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'View' permission for the space to view space + * templates and permission to access the Confluence site ('Can use' global permission) to view global templates. + */ +export async function getContentTemplate(client: Client, parameters: GetContentTemplate): Promise { + const config: SendRequestOptions = { + url: `/wiki/rest/api/template/${parameters.contentTemplateId}`, + method: 'GET', + searchParams: { + expand: parameters.expand, + }, + schema: ContentTemplateSchema, + }; + + return await client.sendRequest(config); +} + +/** + * Deletes a template. This results in different actions depending on the type of template: + * + * - If the template is a content template, it is deleted. + * - If the template is a modified space-level blueprint template, it reverts to the template inherited from the + * global-level blueprint template. + * - If the template is a modified global-level blueprint template, it reverts to the default global-level blueprint + * template. + * + * Note, unmodified blueprint templates cannot be deleted. + * + * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'Admin' permission for the space to delete a + * space template or 'Confluence Administrator' global permission to delete a global template. + */ +export async function removeTemplate(client: Client, parameters: RemoveTemplate): Promise { + const config: SendRequestOptions = { + url: `/wiki/rest/api/template/${parameters.contentTemplateId}`, + method: 'DELETE', + headers: { + 'X-Atlassian-Token': 'no-check', + }, + }; + + return await client.sendRequest(config); +} diff --git a/src/v1/api/themes.ts b/src/v1/api/themes.ts new file mode 100644 index 00000000..1b945be3 --- /dev/null +++ b/src/v1/api/themes.ts @@ -0,0 +1,112 @@ +import { ThemeArraySchema, type ThemeArray } from '../models/themeArray'; +import { ThemeSchema, type Theme } from '../models/theme'; +import type { GetThemes } from '../parameters/getThemes'; +import type { GetTheme } from '../parameters/getTheme'; +import type { GetSpaceTheme } from '../parameters/getSpaceTheme'; +import type { SetSpaceTheme } from '../parameters/setSpaceTheme'; +import type { ResetSpaceTheme } from '../parameters/resetSpaceTheme'; +import type { Client, SendRequestOptions } from '#/core'; + +/** + * Returns all themes, not including the default theme. + * + * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: None + */ +export async function getThemes(client: Client, parameters?: GetThemes): Promise { + const config: SendRequestOptions = { + url: '/wiki/rest/api/settings/theme', + method: 'GET', + searchParams: { + start: parameters?.start, + limit: parameters?.limit, + }, + schema: ThemeArraySchema, + }; + + return await client.sendRequest(config); +} + +/** + * Returns the globally assigned theme. + * + * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: None + */ +export async function getGlobalTheme(client: Client): Promise { + const config: SendRequestOptions = { + url: '/wiki/rest/api/settings/theme/selected', + method: 'GET', + schema: ThemeSchema, + }; + + return await client.sendRequest(config); +} + +/** + * Returns a theme. This includes information about the theme name, description, and icon. + * + * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: None + */ +export async function getTheme(client: Client, parameters: GetTheme): Promise { + const config: SendRequestOptions = { + url: `/wiki/rest/api/settings/theme/${parameters.themeKey}`, + method: 'GET', + schema: ThemeSchema, + }; + + return await client.sendRequest(config); +} + +/** + * Returns the theme selected for a space, if one is set. If no space theme is set, this means that the space is + * inheriting the global look and feel settings. + * + * **[Permissions required](https://confluence.atlassian.com/x/_AozKw)**: ‘View’ permission for the space. + */ +export async function getSpaceTheme(client: Client, parameters: GetSpaceTheme): Promise { + const config: SendRequestOptions = { + url: `/wiki/rest/api/space/${parameters.spaceKey}/theme`, + method: 'GET', + schema: ThemeSchema, + }; + + return await client.sendRequest(config); +} + +/** + * Sets the theme for a space. Note, if you want to reset the space theme to the default Confluence theme, use the + * 'Reset space theme' method instead of this method. + * + * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'Admin' permission for the space. + */ +export async function setSpaceTheme(client: Client, parameters: SetSpaceTheme): Promise { + const config: SendRequestOptions = { + url: `/wiki/rest/api/space/${parameters.spaceKey}/theme`, + method: 'PUT', + headers: { + 'X-Atlassian-Token': 'no-check', + }, + body: { + themeKey: parameters.themeKey, + }, + schema: ThemeSchema, + }; + + return await client.sendRequest(config); +} + +/** + * Resets the space theme. This means that the space will inherit the global look and feel settings + * + * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: 'Admin' permission for the space. + */ +export async function resetSpaceTheme(client: Client, parameters: ResetSpaceTheme): Promise { + const config: SendRequestOptions = { + url: `/wiki/rest/api/space/${parameters.spaceKey}/theme`, + method: 'DELETE', + headers: { + 'X-Atlassian-Token': 'no-check', + }, + }; + + return await client.sendRequest(config); +} diff --git a/src/v1/api/userProperties.ts b/src/v1/api/userProperties.ts new file mode 100644 index 00000000..81d2850f --- /dev/null +++ b/src/v1/api/userProperties.ts @@ -0,0 +1,116 @@ +import { UserPropertyKeyArraySchema, type UserPropertyKeyArray } from '../models/userPropertyKeyArray'; +import { UserPropertySchema, type UserProperty } from '../models/userProperty'; +import type { GetUserProperties } from '../parameters/getUserProperties'; +import type { GetUserProperty } from '../parameters/getUserProperty'; +import type { CreateUserProperty } from '../parameters/createUserProperty'; +import type { UpdateUserProperty } from '../parameters/updateUserProperty'; +import type { DeleteUserProperty } from '../parameters/deleteUserProperty'; +import type { Client, SendRequestOptions } from '#/core'; + +/** + * Returns the properties for a user as list of property keys. For more information about user properties, see + * [Confluence entity properties](https://developer.atlassian.com/cloud/confluence/confluence-entity-properties/). + * `Note`, these properties stored against a user are on a Confluence site level and not space/content level. + * + * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to access the Confluence site ('Can + * use' global permission). + */ +export async function getUserProperties(client: Client, parameters: GetUserProperties): Promise { + const config: SendRequestOptions = { + url: `/wiki/rest/api/user/${parameters.userId}/property`, + method: 'GET', + searchParams: { + start: parameters.start, + limit: parameters.limit, + }, + schema: UserPropertyKeyArraySchema, + }; + + return await client.sendRequest(config); +} + +/** + * Returns the property corresponding to `key` for a user. For more information about user properties, see [Confluence + * entity properties](https://developer.atlassian.com/cloud/confluence/confluence-entity-properties/). `Note`, these + * properties stored against a user are on a Confluence site level and not space/content level. + * + * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to access the Confluence site ('Can + * use' global permission). + */ +export async function getUserProperty(client: Client, parameters: GetUserProperty): Promise { + const config: SendRequestOptions = { + url: `/wiki/rest/api/user/${parameters.userId}/property/${parameters.key}`, + method: 'GET', + schema: UserPropertySchema, + }; + + return await client.sendRequest(config); +} + +/** + * Creates a property for a user. For more information about user properties, see [Confluence entity properties] + * (https://developer.atlassian.com/cloud/confluence/confluence-entity-properties/). `Note`, these properties stored + * against a user are on a Confluence site level and not space/content level. + * + * `Note:` the number of properties which could be created per app in a tenant for each user might be restricted by + * fixed system limits. **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to access the + * Confluence site ('Can use' global permission). + */ +export async function createUserProperty(client: Client, parameters: CreateUserProperty): Promise { + const config: SendRequestOptions = { + url: `/wiki/rest/api/user/${parameters.userId}/property/${parameters.key}`, + method: 'POST', + headers: { + 'X-Atlassian-Token': 'no-check', + }, + body: { + value: parameters.value, + }, + }; + + return await client.sendRequest(config); +} + +/** + * Updates a property for the given user. Note, you cannot update the key of a user property, only the value. For more + * information about user properties, see [Confluence entity + * properties](https://developer.atlassian.com/cloud/confluence/confluence-entity-properties/). `Note`, these properties + * stored against a user are on a Confluence site level and not space/content level. + * + * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to access the Confluence site ('Can + * use' global permission). + */ +export async function updateUserProperty(client: Client, parameters: UpdateUserProperty): Promise { + const config: SendRequestOptions = { + url: `/wiki/rest/api/user/${parameters.userId}/property/${parameters.key}`, + method: 'PUT', + headers: { + 'X-Atlassian-Token': 'no-check', + }, + body: { + value: parameters.value, + }, + }; + + return await client.sendRequest(config); +} + +/** + * Deletes a property for the given user. For more information about user properties, see [Confluence entity + * properties](https://developer.atlassian.com/cloud/confluence/confluence-entity-properties/). `Note`, these properties + * stored against a user are on a Confluence site level and not space/content level. + * + * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to access the Confluence site ('Can + * use' global permission). + */ +export async function deleteUserProperty(client: Client, parameters: DeleteUserProperty): Promise { + const config: SendRequestOptions = { + url: `/wiki/rest/api/user/${parameters.userId}/property/${parameters.key}`, + method: 'DELETE', + headers: { + 'X-Atlassian-Token': 'no-check', + }, + }; + + return await client.sendRequest(config); +} diff --git a/src/v1/api/users.ts b/src/v1/api/users.ts new file mode 100644 index 00000000..43ead0a0 --- /dev/null +++ b/src/v1/api/users.ts @@ -0,0 +1,174 @@ +import { UserSchema, type User } from '../models/user'; +import { UserAnonymousSchema, type UserAnonymous } from '../models/userAnonymous'; +import { GroupArrayWithLinksSchema, type GroupArrayWithLinks } from '../models/groupArrayWithLinks'; +import { BulkUserLookupArraySchema, type BulkUserLookupArray } from '../models/bulkUserLookupArray'; +import { AccountIdEmailRecordSchema, type AccountIdEmailRecord } from '../models/accountIdEmailRecord'; +import { AccountIdEmailRecordArraySchema, type AccountIdEmailRecordArray } from '../models/accountIdEmailRecordArray'; +import type { GetUser } from '../parameters/getUser'; +import type { GetAnonymousUser } from '../parameters/getAnonymousUser'; +import type { GetCurrentUser } from '../parameters/getCurrentUser'; +import type { GetGroupMembershipsForUser } from '../parameters/getGroupMembershipsForUser'; +import type { GetBulkUserLookup } from '../parameters/getBulkUserLookup'; +import type { GetPrivacyUnsafeUserEmail } from '../parameters/getPrivacyUnsafeUserEmail'; +import type { GetPrivacyUnsafeUserEmailBulk } from '../parameters/getPrivacyUnsafeUserEmailBulk'; +import type { Client, SendRequestOptions } from '#/core'; + +/** + * Returns a user. This includes information about the user, such as the display name, account ID, profile picture, and + * more. The information returned may be restricted by the user's profile visibility settings. + * + * **Note:** to add, edit, or delete users in your organization, see the [user management REST + * API](https://developer.atlassian.com/cloud/admin/user-management/about/). + * + * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to access the Confluence site ('Can + * use' global permission). + */ +export async function getUser(client: Client, parameters: GetUser): Promise { + const config: SendRequestOptions = { + url: '/wiki/rest/api/user', + method: 'GET', + searchParams: { + accountId: parameters.accountId, + expand: parameters.expand, + }, + schema: UserSchema, + }; + + return await client.sendRequest(config); +} + +/** + * Returns information about how anonymous users are represented, like the profile picture and display name. + * + * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to access the Confluence site ('Can + * use' global permission). + */ +export async function getAnonymousUser(client: Client, parameters?: GetAnonymousUser): Promise { + const config: SendRequestOptions = { + url: '/wiki/rest/api/user/anonymous', + method: 'GET', + searchParams: { + expand: parameters?.expand, + }, + schema: UserAnonymousSchema, + }; + + return await client.sendRequest(config); +} + +/** + * Returns the currently logged-in user. This includes information about the user, like the display name, userKey, + * account ID, profile picture, and more. + * + * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to access the Confluence site ('Can + * use' global permission). + */ +export async function getCurrentUser(client: Client, parameters?: GetCurrentUser): Promise { + const config: SendRequestOptions = { + url: '/wiki/rest/api/user/current', + method: 'GET', + searchParams: { + expand: parameters?.expand, + }, + schema: UserSchema, + }; + + return await client.sendRequest(config); +} + +/** + * Returns the groups that a user is a member of. + * + * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to access the Confluence site ('Can + * use' global permission). + */ +export async function getGroupMembershipsForUser( + client: Client, + parameters: GetGroupMembershipsForUser, +): Promise { + const config: SendRequestOptions = { + url: '/wiki/rest/api/user/memberof', + method: 'GET', + searchParams: { + accountId: parameters.accountId, + start: parameters.start, + limit: parameters.limit, + }, + schema: GroupArrayWithLinksSchema, + }; + + return await client.sendRequest(config); +} + +/** + * Returns user details for the ids provided in the request. Currently this API returns a maximum of 100 results. If + * more than 100 account ids are passed in, then the first 100 will be returned. + * + * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to access the Confluence site ('Can + * use' global permission). + */ +export async function getBulkUserLookup(client: Client, parameters: GetBulkUserLookup): Promise { + const config: SendRequestOptions = { + url: '/wiki/rest/api/user/bulk', + method: 'GET', + searchParams: { + accountId: parameters.accountId, + expand: parameters.expand, + }, + schema: BulkUserLookupArraySchema, + }; + + return await client.sendRequest(config); +} + +/** + * Returns a user's email address regardless of the user’s profile visibility settings. For Connect apps, this API is + * only available to apps approved by Atlassian, according to these + * [guidelines](https://community.developer.atlassian.com/t/guidelines-for-requesting-access-to-email-address/27603). + * For Forge apps, this API only supports access via asApp() requests. + * + * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to access the Confluence site ('Can + * use' global permission). + */ +export async function getPrivacyUnsafeUserEmail( + client: Client, + parameters: GetPrivacyUnsafeUserEmail, +): Promise { + const config: SendRequestOptions = { + url: '/wiki/rest/api/user/email', + method: 'GET', + searchParams: { + accountId: parameters.accountId, + }, + schema: AccountIdEmailRecordSchema, + }; + + return await client.sendRequest(config); +} + +/** + * Returns a user's email address regardless of the user’s profile visibility settings. For Connect apps, this API is + * only available to apps approved by Atlassian, according to these + * [guidelines](https://community.developer.atlassian.com/t/guidelines-for-requesting-access-to-email-address/27603). + * For Forge apps, this API only supports access via asApp() requests. + * + * Any accounts which are not available will not be included in the result. + * + * **[Permissions](https://confluence.atlassian.com/x/_AozKw) required**: Permission to access the Confluence site ('Can + * use' global permission). + */ +export async function getPrivacyUnsafeUserEmailBulk( + client: Client, + parameters: GetPrivacyUnsafeUserEmailBulk, +): Promise { + const config: SendRequestOptions = { + url: '/wiki/rest/api/user/email/bulk', + method: 'GET', + searchParams: { + accountId: parameters.accountId, + }, + schema: AccountIdEmailRecordArraySchema, + }; + + return await client.sendRequest(config); +} diff --git a/src/v1/createV1Client.ts b/src/v1/createV1Client.ts new file mode 100644 index 00000000..ae6e0eb5 --- /dev/null +++ b/src/v1/createV1Client.ts @@ -0,0 +1,513 @@ +import { type ClientConfig, type Client, createClient, type Buffer } from '#/core'; +import * as audit from './api/audit'; +import * as content from './api/content'; +import * as experimental from './api/experimental'; +import * as contentChildrenAndDescendants from './api/contentChildrenAndDescendants'; +import * as contentAttachments from './api/contentAttachments'; +import * as contentMacroBody from './api/contentMacroBody'; +import * as contentLabels from './api/contentLabels'; +import * as contentWatches from './api/contentWatches'; +import * as contentPermissions from './api/contentPermissions'; +import * as contentRestrictions from './api/contentRestrictions'; +import * as contentStates from './api/contentStates'; +import * as contentVersions from './api/contentVersions'; +import * as contentBody from './api/contentBody'; +import * as labelInfo from './api/labelInfo'; +import * as group from './api/group'; +import * as longRunningTask from './api/longRunningTask'; +import * as relation from './api/relation'; +import * as search from './api/search'; +import * as settings from './api/settings'; +import * as themes from './api/themes'; +import * as space from './api/space'; +import * as spacePermissions from './api/spacePermissions'; +import * as spaceSettings from './api/spaceSettings'; +import * as template from './api/template'; +import * as users from './api/users'; +import * as dynamicModules from './api/dynamicModules'; +import * as analytics from './api/analytics'; +import * as userProperties from './api/userProperties'; +import type { + GetAuditRecords, + CreateAuditRecord, + ExportAuditRecords, + SetRetentionPeriod, + GetAuditRecordsForTimePeriod, + ArchivePages, + PublishLegacyDraft, + PublishSharedDraft, + SearchContentByCQL, + DeletePageTree, + GetLabelsForSpace, + AddLabelsToSpace, + DeleteLabelFromSpace, + MovePage, + GetContentDescendants, + GetDescendantsOfType, + CopyPageHierarchy, + CopyPage, + CreateAttachment, + CreateOrUpdateAttachments, + UpdateAttachmentProperties, + UpdateAttachmentData, + DownloadAttatchment, + GetMacroBodyByMacroId, + GetAndConvertMacroBodyByMacroId, + GetAndAsyncConvertMacroBodyByMacroId, + AddLabelsToContent, + RemoveLabelFromContentUsingQueryParameter, + RemoveLabelFromContent, + GetWatchesForPage, + GetWatchesForSpace, + GetWatchersForSpace, + GetContentWatchStatus, + AddContentWatcher, + RemoveContentWatcher, + IsWatchingLabel, + AddLabelWatcher, + RemoveLabelWatcher, + IsWatchingSpace, + AddSpaceWatcher, + RemoveSpaceWatch, + CheckContentPermission, + GetRestrictions, + AddRestrictions, + UpdateRestrictions, + DeleteRestrictions, + GetRestrictionsByOperation, + GetRestrictionsForOperation, + GetIndividualGroupRestrictionStatusByGroupId, + AddGroupToContentRestrictionByGroupId, + RemoveGroupFromContentRestriction, + GetContentRestrictionStatusForUser, + AddUserToContentRestriction, + RemoveUserFromContentRestriction, + GetContentState, + SetContentState, + RemoveContentState, + GetAvailableContentStates, + GetSpaceContentStates, + GetContentStateSettings, + GetContentsWithState, + RestoreContentVersion, + DeleteContentVersion, + AsyncConvertContentBodyRequest, + AsyncConvertContentBodyResponse, + BulkAsyncConvertContentBodyResponse, + BulkAsyncConvertContentBodyRequest, + GetAllLabelContent, + GetGroups, + CreateGroup, + GetGroupByGroupId, + RemoveGroupById, + SearchGroups, + GetGroupMembersByGroupId, + AddUserToGroupByGroupId, + RemoveMemberFromGroupByGroupId, + GetTasks, + GetTask, + FindTargetFromSource, + GetRelationship, + CreateRelationship, + DeleteRelationship, + FindSourcesForTarget, + SearchByCQL, + SearchUser, + GetLookAndFeelSettings, + UpdateLookAndFeel, + UpdateLookAndFeelSettings, + ResetLookAndFeelSettings, + GetThemes, + GetTheme, + GetSpaceTheme, + SetSpaceTheme, + ResetSpaceTheme, + CreateSpace, + CreatePrivateSpace, + UpdateSpace, + DeleteSpace, + AddPermissionToSpace, + AddCustomContentPermissions, + RemovePermission, + GetSpaceSettings, + UpdateSpaceSettings, + CreateContentTemplate, + UpdateContentTemplate, + GetBlueprintTemplates, + GetContentTemplates, + GetContentTemplate, + RemoveTemplate, + GetUser, + GetAnonymousUser, + GetCurrentUser, + GetGroupMembershipsForUser, + GetBulkUserLookup, + GetPrivacyUnsafeUserEmail, + GetPrivacyUnsafeUserEmailBulk, + RegisterModules, + RemoveModules, + GetViews, + GetViewers, + GetUserProperties, + GetUserProperty, + CreateUserProperty, + UpdateUserProperty, + DeleteUserProperty, +} from './parameters'; +import type { + AuditRecordArray, + AuditRecord, + RetentionPeriod, + LongTask, + Content, + ContentArray, + LabelArray, + MovePage as MovePageModel, + ContentChildren, + MacroInstance, + ContentBody, + AsyncId, + WatchArray, + SpaceWatchArray, + UserWatch, + PermissionCheckResponse, + ContentRestrictionArray, + ContentRestriction, + ContentStateResponse, + AvailableContentStates, + ContentState, + ContentStateSettings, + Version, + AsyncContentBody, + AsyncContentBodyArray, + AsyncIdArray, + LabelDetails, + GroupArrayWithLinks, + Group, + UserArray, + LongTaskStatusArray, + LongTaskStatusWithLinks, + RelationArray, + Relation, + SearchPageResponseSearchResult, + LookAndFeelSettings, + LookAndFeelSelection, + LookAndFeelWithLinks, + SystemInfoEntity, + ThemeArray, + Theme, + Space, + SpacePermissionV2, + SpaceSettings, + ContentTemplate, + BlueprintTemplateArray, + ContentTemplateArray, + User, + UserAnonymous, + BulkUserLookupArray, + AccountIdEmailRecord, + AccountIdEmailRecordArray, + GetViews as GetViewsModel, + GetViewers as GetViewersModel, + UserPropertyKeyArray, + UserProperty, +} from './models'; + +export function createV1Client(clientConfig: ClientConfig | Client) { + const client = createClient(clientConfig); + + return { + audit: { + getAuditRecords: (parameters?: GetAuditRecords): Promise => + audit.getAuditRecords(client, parameters), + createAuditRecord: (parameters: CreateAuditRecord): Promise => + audit.createAuditRecord(client, parameters), + exportAuditRecords: (parameters?: ExportAuditRecords): Promise => + audit.exportAuditRecords(client, parameters), + getRetentionPeriod: (): Promise => audit.getRetentionPeriod(client), + setRetentionPeriod: (parameters: SetRetentionPeriod): Promise => + audit.setRetentionPeriod(client, parameters), + getAuditRecordsForTimePeriod: (parameters?: GetAuditRecordsForTimePeriod): Promise => + audit.getAuditRecordsForTimePeriod(client, parameters), + }, + content: { + archivePages: (parameters: ArchivePages): Promise => content.archivePages(client, parameters), + publishLegacyDraft: (parameters: PublishLegacyDraft): Promise => + content.publishLegacyDraft(client, parameters), + publishSharedDraft: (parameters: PublishSharedDraft): Promise => + content.publishSharedDraft(client, parameters), + searchContentByCQL: (parameters: SearchContentByCQL): Promise => + content.searchContentByCQL(client, parameters), + }, + experimental: { + deletePageTree: (parameters: DeletePageTree): Promise => + experimental.deletePageTree(client, parameters), + getLabelsForSpace: (parameters: GetLabelsForSpace): Promise => + experimental.getLabelsForSpace(client, parameters), + addLabelsToSpace: (parameters: AddLabelsToSpace): Promise => + experimental.addLabelsToSpace(client, parameters), + deleteLabelFromSpace: (parameters: DeleteLabelFromSpace): Promise => + experimental.deleteLabelFromSpace(client, parameters), + }, + contentChildrenAndDescendants: { + movePage: (parameters: MovePage): Promise => + contentChildrenAndDescendants.movePage(client, parameters), + getContentDescendants: (parameters: GetContentDescendants): Promise => + contentChildrenAndDescendants.getContentDescendants(client, parameters), + getDescendantsOfType: (parameters: GetDescendantsOfType): Promise => + contentChildrenAndDescendants.getDescendantsOfType(client, parameters), + copyPageHierarchy: (parameters: CopyPageHierarchy): Promise => + contentChildrenAndDescendants.copyPageHierarchy(client, parameters), + copyPage: (parameters: CopyPage): Promise => contentChildrenAndDescendants.copyPage(client, parameters), + }, + contentAttachments: { + createAttachment: (parameters: CreateAttachment): Promise => + contentAttachments.createAttachment(client, parameters), + createOrUpdateAttachments: (parameters: CreateOrUpdateAttachments): Promise => + contentAttachments.createOrUpdateAttachments(client, parameters), + updateAttachmentProperties: (parameters: UpdateAttachmentProperties): Promise => + contentAttachments.updateAttachmentProperties(client, parameters), + updateAttachmentData: (parameters: UpdateAttachmentData): Promise => + contentAttachments.updateAttachmentData(client, parameters), + downloadAttatchment: (parameters: DownloadAttatchment): Promise => + contentAttachments.downloadAttatchment(client, parameters), + }, + contentMacroBody: { + getMacroBodyByMacroId: (parameters: GetMacroBodyByMacroId): Promise => + contentMacroBody.getMacroBodyByMacroId(client, parameters), + getAndConvertMacroBodyByMacroId: (parameters: GetAndConvertMacroBodyByMacroId): Promise => + contentMacroBody.getAndConvertMacroBodyByMacroId(client, parameters), + getAndAsyncConvertMacroBodyByMacroId: (parameters: GetAndAsyncConvertMacroBodyByMacroId): Promise => + contentMacroBody.getAndAsyncConvertMacroBodyByMacroId(client, parameters), + }, + contentLabels: { + addLabelsToContent: (parameters: AddLabelsToContent): Promise => + contentLabels.addLabelsToContent(client, parameters), + removeLabelFromContentUsingQueryParameter: ( + parameters: RemoveLabelFromContentUsingQueryParameter, + ): Promise => contentLabels.removeLabelFromContentUsingQueryParameter(client, parameters), + removeLabelFromContent: (parameters: RemoveLabelFromContent): Promise => + contentLabels.removeLabelFromContent(client, parameters), + }, + contentWatches: { + getWatchesForPage: (parameters: GetWatchesForPage): Promise => + contentWatches.getWatchesForPage(client, parameters), + getWatchesForSpace: (parameters: GetWatchesForSpace): Promise => + contentWatches.getWatchesForSpace(client, parameters), + getWatchersForSpace: (parameters: GetWatchersForSpace): Promise => + contentWatches.getWatchersForSpace(client, parameters), + getContentWatchStatus: (parameters: GetContentWatchStatus): Promise => + contentWatches.getContentWatchStatus(client, parameters), + addContentWatcher: (parameters: AddContentWatcher): Promise => + contentWatches.addContentWatcher(client, parameters), + removeContentWatcher: (parameters: RemoveContentWatcher): Promise => + contentWatches.removeContentWatcher(client, parameters), + isWatchingLabel: (parameters: IsWatchingLabel): Promise => + contentWatches.isWatchingLabel(client, parameters), + addLabelWatcher: (parameters: AddLabelWatcher): Promise => + contentWatches.addLabelWatcher(client, parameters), + removeLabelWatcher: (parameters: RemoveLabelWatcher): Promise => + contentWatches.removeLabelWatcher(client, parameters), + isWatchingSpace: (parameters: IsWatchingSpace): Promise => + contentWatches.isWatchingSpace(client, parameters), + addSpaceWatcher: (parameters: AddSpaceWatcher): Promise => + contentWatches.addSpaceWatcher(client, parameters), + removeSpaceWatch: (parameters: RemoveSpaceWatch): Promise => + contentWatches.removeSpaceWatch(client, parameters), + }, + contentPermissions: { + checkContentPermission: (parameters: CheckContentPermission): Promise => + contentPermissions.checkContentPermission(client, parameters), + }, + contentRestrictions: { + getRestrictions: (parameters: GetRestrictions): Promise => + contentRestrictions.getRestrictions(client, parameters), + addRestrictions: (parameters: AddRestrictions): Promise => + contentRestrictions.addRestrictions(client, parameters), + updateRestrictions: (parameters: UpdateRestrictions): Promise => + contentRestrictions.updateRestrictions(client, parameters), + deleteRestrictions: (parameters: DeleteRestrictions): Promise => + contentRestrictions.deleteRestrictions(client, parameters), + getRestrictionsByOperation: (parameters: GetRestrictionsByOperation): Promise => + contentRestrictions.getRestrictionsByOperation(client, parameters), + getRestrictionsForOperation: (parameters: GetRestrictionsForOperation): Promise => + contentRestrictions.getRestrictionsForOperation(client, parameters), + getIndividualGroupRestrictionStatusByGroupId: ( + parameters: GetIndividualGroupRestrictionStatusByGroupId, + ): Promise => contentRestrictions.getIndividualGroupRestrictionStatusByGroupId(client, parameters), + addGroupToContentRestrictionByGroupId: (parameters: AddGroupToContentRestrictionByGroupId): Promise => + contentRestrictions.addGroupToContentRestrictionByGroupId(client, parameters), + removeGroupFromContentRestriction: (parameters: RemoveGroupFromContentRestriction): Promise => + contentRestrictions.removeGroupFromContentRestriction(client, parameters), + getContentRestrictionStatusForUser: (parameters: GetContentRestrictionStatusForUser): Promise => + contentRestrictions.getContentRestrictionStatusForUser(client, parameters), + addUserToContentRestriction: (parameters: AddUserToContentRestriction): Promise => + contentRestrictions.addUserToContentRestriction(client, parameters), + removeUserFromContentRestriction: (parameters: RemoveUserFromContentRestriction): Promise => + contentRestrictions.removeUserFromContentRestriction(client, parameters), + }, + contentStates: { + getContentState: (parameters: GetContentState): Promise => + contentStates.getContentState(client, parameters), + setContentState: (parameters: SetContentState): Promise => + contentStates.setContentState(client, parameters), + removeContentState: (parameters: RemoveContentState): Promise => + contentStates.removeContentState(client, parameters), + getAvailableContentStates: (parameters: GetAvailableContentStates): Promise => + contentStates.getAvailableContentStates(client, parameters), + getCustomContentStates: (): Promise => contentStates.getCustomContentStates(client), + getSpaceContentStates: (parameters: GetSpaceContentStates): Promise => + contentStates.getSpaceContentStates(client, parameters), + getContentStateSettings: (parameters: GetContentStateSettings): Promise => + contentStates.getContentStateSettings(client, parameters), + getContentsWithState: (parameters: GetContentsWithState): Promise => + contentStates.getContentsWithState(client, parameters), + }, + contentVersions: { + restoreContentVersion: (parameters: RestoreContentVersion): Promise => + contentVersions.restoreContentVersion(client, parameters), + deleteContentVersion: (parameters: DeleteContentVersion): Promise => + contentVersions.deleteContentVersion(client, parameters), + }, + contentBody: { + asyncConvertContentBodyRequest: (parameters: AsyncConvertContentBodyRequest): Promise => + contentBody.asyncConvertContentBodyRequest(client, parameters), + asyncConvertContentBodyResponse: (parameters: AsyncConvertContentBodyResponse): Promise => + contentBody.asyncConvertContentBodyResponse(client, parameters), + bulkAsyncConvertContentBodyResponse: ( + parameters: BulkAsyncConvertContentBodyResponse, + ): Promise => contentBody.bulkAsyncConvertContentBodyResponse(client, parameters), + bulkAsyncConvertContentBodyRequest: (parameters: BulkAsyncConvertContentBodyRequest): Promise => + contentBody.bulkAsyncConvertContentBodyRequest(client, parameters), + }, + labelInfo: { + getAllLabelContent: (parameters: GetAllLabelContent): Promise => + labelInfo.getAllLabelContent(client, parameters), + }, + group: { + getGroups: (parameters?: GetGroups): Promise => group.getGroups(client, parameters), + createGroup: (parameters: CreateGroup): Promise => group.createGroup(client, parameters), + getGroupByGroupId: (parameters: GetGroupByGroupId): Promise => group.getGroupByGroupId(client, parameters), + removeGroupById: (parameters: RemoveGroupById): Promise => group.removeGroupById(client, parameters), + searchGroups: (parameters: SearchGroups): Promise => group.searchGroups(client, parameters), + getGroupMembersByGroupId: (parameters: GetGroupMembersByGroupId): Promise => + group.getGroupMembersByGroupId(client, parameters), + addUserToGroupByGroupId: (parameters: AddUserToGroupByGroupId): Promise => + group.addUserToGroupByGroupId(client, parameters), + removeMemberFromGroupByGroupId: (parameters: RemoveMemberFromGroupByGroupId): Promise => + group.removeMemberFromGroupByGroupId(client, parameters), + }, + longRunningTask: { + getTasks: (parameters?: GetTasks): Promise => longRunningTask.getTasks(client, parameters), + getTask: (parameters: GetTask): Promise => longRunningTask.getTask(client, parameters), + }, + relation: { + findTargetFromSource: (parameters: FindTargetFromSource): Promise => + relation.findTargetFromSource(client, parameters), + getRelationship: (parameters: GetRelationship): Promise => relation.getRelationship(client, parameters), + createRelationship: (parameters: CreateRelationship): Promise => + relation.createRelationship(client, parameters), + deleteRelationship: (parameters: DeleteRelationship): Promise => + relation.deleteRelationship(client, parameters), + findSourcesForTarget: (parameters: FindSourcesForTarget): Promise => + relation.findSourcesForTarget(client, parameters), + }, + search: { + searchByCQL: (parameters: SearchByCQL): Promise => + search.searchByCQL(client, parameters), + searchUser: (parameters: SearchUser): Promise => + search.searchUser(client, parameters), + }, + settings: { + getLookAndFeelSettings: (parameters?: GetLookAndFeelSettings): Promise => + settings.getLookAndFeelSettings(client, parameters), + updateLookAndFeel: (parameters: UpdateLookAndFeel): Promise => + settings.updateLookAndFeel(client, parameters), + updateLookAndFeelSettings: (parameters: UpdateLookAndFeelSettings): Promise => + settings.updateLookAndFeelSettings(client, parameters), + resetLookAndFeelSettings: (parameters: ResetLookAndFeelSettings): Promise => + settings.resetLookAndFeelSettings(client, parameters), + getSystemInfo: (): Promise => settings.getSystemInfo(client), + }, + themes: { + getThemes: (parameters?: GetThemes): Promise => themes.getThemes(client, parameters), + getGlobalTheme: (): Promise => themes.getGlobalTheme(client), + getTheme: (parameters: GetTheme): Promise => themes.getTheme(client, parameters), + getSpaceTheme: (parameters: GetSpaceTheme): Promise => themes.getSpaceTheme(client, parameters), + setSpaceTheme: (parameters: SetSpaceTheme): Promise => themes.setSpaceTheme(client, parameters), + resetSpaceTheme: (parameters: ResetSpaceTheme): Promise => themes.resetSpaceTheme(client, parameters), + }, + space: { + createSpace: (parameters: CreateSpace): Promise => space.createSpace(client, parameters), + createPrivateSpace: (parameters: CreatePrivateSpace): Promise => + space.createPrivateSpace(client, parameters), + updateSpace: (parameters: UpdateSpace): Promise => space.updateSpace(client, parameters), + deleteSpace: (parameters: DeleteSpace): Promise => space.deleteSpace(client, parameters), + }, + spacePermissions: { + addPermissionToSpace: (parameters: AddPermissionToSpace): Promise => + spacePermissions.addPermissionToSpace(client, parameters), + addCustomContentPermissions: (parameters: AddCustomContentPermissions): Promise => + spacePermissions.addCustomContentPermissions(client, parameters), + removePermission: (parameters: RemovePermission): Promise => + spacePermissions.removePermission(client, parameters), + }, + spaceSettings: { + getSpaceSettings: (parameters: GetSpaceSettings): Promise => + spaceSettings.getSpaceSettings(client, parameters), + updateSpaceSettings: (parameters: UpdateSpaceSettings): Promise => + spaceSettings.updateSpaceSettings(client, parameters), + }, + template: { + createContentTemplate: (parameters: CreateContentTemplate): Promise => + template.createContentTemplate(client, parameters), + updateContentTemplate: (parameters: UpdateContentTemplate): Promise => + template.updateContentTemplate(client, parameters), + getBlueprintTemplates: (parameters?: GetBlueprintTemplates): Promise => + template.getBlueprintTemplates(client, parameters), + getContentTemplates: (parameters?: GetContentTemplates): Promise => + template.getContentTemplates(client, parameters), + getContentTemplate: (parameters: GetContentTemplate): Promise => + template.getContentTemplate(client, parameters), + removeTemplate: (parameters: RemoveTemplate): Promise => template.removeTemplate(client, parameters), + }, + users: { + getUser: (parameters: GetUser): Promise => users.getUser(client, parameters), + getAnonymousUser: (parameters?: GetAnonymousUser): Promise => + users.getAnonymousUser(client, parameters), + getCurrentUser: (parameters?: GetCurrentUser): Promise => users.getCurrentUser(client, parameters), + getGroupMembershipsForUser: (parameters: GetGroupMembershipsForUser): Promise => + users.getGroupMembershipsForUser(client, parameters), + getBulkUserLookup: (parameters: GetBulkUserLookup): Promise => + users.getBulkUserLookup(client, parameters), + getPrivacyUnsafeUserEmail: (parameters: GetPrivacyUnsafeUserEmail): Promise => + users.getPrivacyUnsafeUserEmail(client, parameters), + getPrivacyUnsafeUserEmailBulk: (parameters: GetPrivacyUnsafeUserEmailBulk): Promise => + users.getPrivacyUnsafeUserEmailBulk(client, parameters), + }, + dynamicModules: { + getModules: (): Promise => dynamicModules.getModules(client), + registerModules: (parameters: RegisterModules): Promise => + dynamicModules.registerModules(client, parameters), + removeModules: (parameters: RemoveModules): Promise => dynamicModules.removeModules(client, parameters), + }, + analytics: { + getViews: (parameters: GetViews): Promise => analytics.getViews(client, parameters), + getViewers: (parameters: GetViewers): Promise => analytics.getViewers(client, parameters), + }, + userProperties: { + getUserProperties: (parameters: GetUserProperties): Promise => + userProperties.getUserProperties(client, parameters), + getUserProperty: (parameters: GetUserProperty): Promise => + userProperties.getUserProperty(client, parameters), + createUserProperty: (parameters: CreateUserProperty): Promise => + userProperties.createUserProperty(client, parameters), + updateUserProperty: (parameters: UpdateUserProperty): Promise => + userProperties.updateUserProperty(client, parameters), + deleteUserProperty: (parameters: DeleteUserProperty): Promise => + userProperties.deleteUserProperty(client, parameters), + }, + }; +} + +export type V1Client = ReturnType; diff --git a/src/v1/index.ts b/src/v1/index.ts new file mode 100644 index 00000000..c2c4106f --- /dev/null +++ b/src/v1/index.ts @@ -0,0 +1,5 @@ +export * from './api'; + +export * from './models'; + +export * from './createV1Client'; diff --git a/src/v1/models/accountId.ts b/src/v1/models/accountId.ts new file mode 100644 index 00000000..a4ff4dcf --- /dev/null +++ b/src/v1/models/accountId.ts @@ -0,0 +1,8 @@ +import { z } from 'zod'; +import { apiObject } from '#/core'; + +export const AccountIdSchema = apiObject({ + accountId: z.string(), +}); + +export type AccountId = z.infer; diff --git a/src/v1/models/accountIdEmailRecord.ts b/src/v1/models/accountIdEmailRecord.ts new file mode 100644 index 00000000..476dcc5a --- /dev/null +++ b/src/v1/models/accountIdEmailRecord.ts @@ -0,0 +1,9 @@ +import { z } from 'zod'; +import { apiObject } from '#/core'; + +export const AccountIdEmailRecordSchema = apiObject({ + accountId: z.string(), + email: z.string(), +}); + +export type AccountIdEmailRecord = z.infer; diff --git a/src/v1/models/accountIdEmailRecordArray.ts b/src/v1/models/accountIdEmailRecordArray.ts new file mode 100644 index 00000000..bf557f39 --- /dev/null +++ b/src/v1/models/accountIdEmailRecordArray.ts @@ -0,0 +1,6 @@ +import { z } from 'zod'; +import { AccountIdEmailRecordSchema } from './accountIdEmailRecord'; + +export const AccountIdEmailRecordArraySchema = z.array(AccountIdEmailRecordSchema); + +export type AccountIdEmailRecordArray = z.infer; diff --git a/src/v1/models/addContentRestriction.ts b/src/v1/models/addContentRestriction.ts new file mode 100644 index 00000000..142d1311 --- /dev/null +++ b/src/v1/models/addContentRestriction.ts @@ -0,0 +1,47 @@ +import { z } from 'zod'; +import { apiObject } from '#/core'; +import { GenericUserNameSchema } from './genericUserName'; +import { GenericUserKeySchema } from './genericUserKey'; +import { GenericAccountIdSchema } from './genericAccountId'; + +export const AddContentRestrictionSchema = apiObject({ + /** The restriction operation applied to content. */ + operation: z.enum(['read', 'update']), + /** + * The users/groups that the restrictions will be applied to. At least one of `user` or `group` must be specified + * for this object. + */ + restrictions: apiObject({ + /** + * The users that the restrictions will be applied to. This array must have at least one item, otherwise it + * should be omitted. + */ + user: z + .array( + apiObject({ + /** Set to 'known'. */ + type: z.enum(['known', 'unknown', 'anonymous', 'user']), + username: GenericUserNameSchema.optional(), + userKey: GenericUserKeySchema.optional(), + accountId: GenericAccountIdSchema, + }), + ) + .optional(), + /** + * The groups that the restrictions will be applied to. This array must have at least one item, otherwise it + * should be omitted. + */ + group: z + .array( + apiObject({ + /** Set to 'group'. */ + type: z.enum(['group']), + /** The name of the group. */ + name: z.string(), + }), + ) + .optional(), + }), +}); + +export type AddContentRestriction = z.infer; diff --git a/src/v1/models/addContentRestrictionUpdateArray.ts b/src/v1/models/addContentRestrictionUpdateArray.ts new file mode 100644 index 00000000..579e90be --- /dev/null +++ b/src/v1/models/addContentRestrictionUpdateArray.ts @@ -0,0 +1,6 @@ +import { z } from 'zod'; +import { AddContentRestrictionSchema } from './addContentRestriction'; + +export const AddContentRestrictionUpdateArraySchema = z.array(AddContentRestrictionSchema); + +export type AddContentRestrictionUpdateArray = z.infer; diff --git a/src/v1/models/affectedObject.ts b/src/v1/models/affectedObject.ts new file mode 100644 index 00000000..26c664b6 --- /dev/null +++ b/src/v1/models/affectedObject.ts @@ -0,0 +1,9 @@ +import { z } from 'zod'; +import { apiObject } from '#/core'; + +export const AffectedObjectSchema = apiObject({ + name: z.string(), + objectType: z.string(), +}); + +export type AffectedObject = z.infer; diff --git a/src/v1/models/asyncContentBody.ts b/src/v1/models/asyncContentBody.ts new file mode 100644 index 00000000..3cde9475 --- /dev/null +++ b/src/v1/models/asyncContentBody.ts @@ -0,0 +1,47 @@ +import { z } from 'zod'; +import { apiObject } from '#/core'; +import { EmbeddedContentSchema } from './embeddedContent'; +import { WebResourceDependenciesSchema } from './webResourceDependencies'; +import { GenericLinksSchema } from './genericLinks'; + +export const AsyncContentBodySchema = apiObject({ + value: z.string().optional(), + representation: z + .enum([ + 'view', + 'export_view', + 'styled_view', + 'storage', + 'editor', + 'editor2', + 'anonymous_export_view', + 'wiki', + 'atlas_doc_format', + ]) + .optional(), + renderTaskId: z.string().optional(), + error: z.string().optional(), + /** + * Rerunning is reserved for when the job is working, but there is a previous run's value in the cache. You may + * choose to continue polling, or use the cached value. + */ + status: z.enum(['WORKING', 'QUEUED', 'FAILED', 'COMPLETED', 'RERUNNING']).optional(), + embeddedContent: z.array(EmbeddedContentSchema).optional(), + webresource: WebResourceDependenciesSchema.nullish(), + mediaToken: apiObject({ + collectionIds: z.array(z.string()).optional(), + contentId: z.string().optional(), + expiryDateTime: z.string().optional(), + fileIds: z.array(z.string()).optional(), + token: z.string().optional(), + }).nullish(), + _expandable: apiObject({ + content: z.string().optional(), + embeddedContent: z.string().optional(), + webresource: z.string().optional(), + mediaToken: z.string().optional(), + }).optional(), + _links: GenericLinksSchema.optional(), +}); + +export type AsyncContentBody = z.infer; diff --git a/src/v1/models/asyncContentBodyArray.ts b/src/v1/models/asyncContentBodyArray.ts new file mode 100644 index 00000000..44c3bac4 --- /dev/null +++ b/src/v1/models/asyncContentBodyArray.ts @@ -0,0 +1,6 @@ +import { z } from 'zod'; +import { AsyncContentBodySchema } from './asyncContentBody'; + +export const AsyncContentBodyArraySchema = z.array(AsyncContentBodySchema); + +export type AsyncContentBodyArray = z.infer; diff --git a/src/v1/models/asyncId.ts b/src/v1/models/asyncId.ts new file mode 100644 index 00000000..afd95713 --- /dev/null +++ b/src/v1/models/asyncId.ts @@ -0,0 +1,8 @@ +import { z } from 'zod'; +import { apiObject } from '#/core'; + +export const AsyncIdSchema = apiObject({ + asyncId: z.string(), +}); + +export type AsyncId = z.infer; diff --git a/src/v1/models/asyncIdArray.ts b/src/v1/models/asyncIdArray.ts new file mode 100644 index 00000000..f9acdcfa --- /dev/null +++ b/src/v1/models/asyncIdArray.ts @@ -0,0 +1,6 @@ +import { z } from 'zod'; +import { AsyncIdSchema } from './asyncId'; + +export const AsyncIdArraySchema = z.array(AsyncIdSchema); + +export type AsyncIdArray = z.infer; diff --git a/src/v1/models/attachmentPropertiesUpdateBody.ts b/src/v1/models/attachmentPropertiesUpdateBody.ts new file mode 100644 index 00000000..9ce4ce91 --- /dev/null +++ b/src/v1/models/attachmentPropertiesUpdateBody.ts @@ -0,0 +1,20 @@ +import { z } from 'zod'; +import { apiObject } from '#/core'; +import { ContainerSchema } from './container'; +import { VersionSchema } from './version'; + +export const AttachmentPropertiesUpdateBodySchema = apiObject({ + id: z.string(), + /** Set this to "attachment" */ + type: z.string(), + status: z.string().optional(), + title: z.string().optional(), + container: ContainerSchema.optional(), + metadata: apiObject({ + mediaType: z.string().optional(), + }).optional(), + extensions: z.record(z.string(), z.any()).optional(), + version: VersionSchema, +}); + +export type AttachmentPropertiesUpdateBody = z.infer; diff --git a/src/v1/models/attachmentUpdate.ts b/src/v1/models/attachmentUpdate.ts new file mode 100644 index 00000000..2224af22 --- /dev/null +++ b/src/v1/models/attachmentUpdate.ts @@ -0,0 +1,34 @@ +import { z } from 'zod'; +import { apiObject } from '#/core'; + +export const AttachmentUpdateSchema = apiObject({ + /** + * The attachment version. Set this to the current version number of the attachment. Note, the version number only + * needs to be incremented when updating the actual attachment, not its properties. + */ + version: apiObject({ + /** The version number. */ + number: z.number(), + }), + /** The ID of the attachment to be updated. */ + id: z.string(), + /** Set this to `attachment`. */ + type: z.enum(['attachment']), + /** The updated name of the attachment. */ + title: z.string().max(255, 'title must be at most 255 characters').optional(), + metadata: apiObject({ + /** The media type of the attachment, e.g. 'img/jpg'. */ + mediaType: z.string().optional(), + /** The comment for this update. */ + comment: z.string().optional(), + }).optional(), + /** The new content to attach the attachment to. */ + container: apiObject({ + /** The `id` of the parent content. */ + id: z.string(), + /** The content type. You can only attach attachments to content of type: `page`, `blogpost`. */ + type: z.string(), + }).optional(), +}); + +export type AttachmentUpdate = z.infer; diff --git a/src/v1/models/auditRecord.ts b/src/v1/models/auditRecord.ts new file mode 100644 index 00000000..94986c04 --- /dev/null +++ b/src/v1/models/auditRecord.ts @@ -0,0 +1,41 @@ +import { z } from 'zod'; +import { apiObject } from '#/core'; +import { OperationCheckResultSchema } from './operationCheckResult'; +import { GenericUserNameSchema } from './genericUserName'; +import { GenericUserKeySchema } from './genericUserKey'; +import { GenericAccountIdSchema } from './genericAccountId'; +import { AffectedObjectSchema } from './affectedObject'; +import { ChangedValueSchema } from './changedValue'; + +export const AuditRecordSchema = apiObject({ + author: apiObject({ + type: z.enum(['user']), + displayName: z.string(), + operations: z.array(OperationCheckResultSchema).nullish(), + username: GenericUserNameSchema.optional(), + userKey: GenericUserKeySchema.optional(), + accountId: GenericAccountIdSchema.optional(), + accountType: z.string().optional(), + /** This is deprecated. Use `isGuest` instead. */ + externalCollaborator: z.boolean().optional(), + /** This is deprecated. Use `isGuest` instead. Whether the user is an external collaborator user */ + isExternalCollaborator: z.boolean().optional(), + /** Whether the user is a guest user */ + isGuest: z.boolean().optional(), + /** The public name or nickname of the user. Will always contain a value. */ + publicName: z.string().optional(), + }), + remoteAddress: z.string(), + /** The creation date-time of the audit record, as a timestamp. */ + creationDate: z.number(), + summary: z.string(), + description: z.string(), + category: z.string(), + sysAdmin: z.boolean(), + superAdmin: z.boolean().optional(), + affectedObject: AffectedObjectSchema, + changedValues: z.array(ChangedValueSchema), + associatedObjects: z.array(AffectedObjectSchema), +}); + +export type AuditRecord = z.infer; diff --git a/src/v1/models/auditRecordArray.ts b/src/v1/models/auditRecordArray.ts new file mode 100644 index 00000000..d05d2f87 --- /dev/null +++ b/src/v1/models/auditRecordArray.ts @@ -0,0 +1,14 @@ +import { z } from 'zod'; +import { apiObject } from '#/core'; +import { AuditRecordSchema } from './auditRecord'; +import { GenericLinksSchema } from './genericLinks'; + +export const AuditRecordArraySchema = apiObject({ + results: z.array(AuditRecordSchema), + start: z.number(), + limit: z.number(), + size: z.number(), + _links: GenericLinksSchema, +}); + +export type AuditRecordArray = z.infer; diff --git a/src/v1/models/auditRecordCreate.ts b/src/v1/models/auditRecordCreate.ts new file mode 100644 index 00000000..1e109ef2 --- /dev/null +++ b/src/v1/models/auditRecordCreate.ts @@ -0,0 +1,53 @@ +import { z } from 'zod'; +import { apiObject } from '#/core'; +import { OperationCheckResultSchema } from './operationCheckResult'; +import { GenericUserNameSchema } from './genericUserName'; +import { GenericUserKeySchema } from './genericUserKey'; +import { AffectedObjectSchema } from './affectedObject'; +import { ChangedValueSchema } from './changedValue'; + +export const AuditRecordCreateSchema = apiObject({ + /** + * The user that actioned the event. If `author` is not specified, then all `author` properties will be set to + * null/empty, except for `type` which will be set to 'user'. + */ + author: apiObject({ + /** Set to 'user'. */ + type: z.enum(['user']), + /** The name that is displayed on the audit log in the Confluence UI. */ + displayName: z.string().optional(), + /** Always defaults to null. */ + operations: z.array(OperationCheckResultSchema).optional(), + username: GenericUserNameSchema.optional(), + userKey: GenericUserKeySchema.optional(), + }).optional(), + /** The IP address of the computer where the event was initiated from. */ + remoteAddress: z.string(), + /** + * The creation date-time of the audit record, as a timestamp. This is converted to a date-time display in the + * Confluence UI. If the `creationDate` is not specified, then it will be set to the timestamp for the current + * date-time. + */ + creationDate: z.number().optional(), + /** The summary of the event, which is displayed in the 'Change' column on the audit log in the Confluence UI. */ + summary: z.string().optional(), + /** + * A long description of the event, which is displayed in the 'Description' field on the audit log in the Confluence + * UI. + */ + description: z.string().optional(), + /** The category of the event, which is displayed in the 'Event type' column on the audit log in the Confluence UI. */ + category: z.string().optional(), + /** Indicates whether the event was actioned by a system administrator. */ + sysAdmin: z.boolean().optional(), + affectedObject: AffectedObjectSchema.optional(), + /** The values that were changed in the event. */ + changedValues: z.array(ChangedValueSchema).optional(), + /** + * Objects that were associated with the event. For example, if the event was a space permission change then the + * associated object would be the space. + */ + associatedObjects: z.array(AffectedObjectSchema).optional(), +}); + +export type AuditRecordCreate = z.infer; diff --git a/src/v1/models/availableContentStates.ts b/src/v1/models/availableContentStates.ts new file mode 100644 index 00000000..b057e6dd --- /dev/null +++ b/src/v1/models/availableContentStates.ts @@ -0,0 +1,21 @@ +import { z } from 'zod'; +import { apiObject } from '#/core'; +import { ContentStateSchema } from './contentState'; + +export const AvailableContentStatesSchema = apiObject({ + /** + * Space suggested content states that can be used in the space. This list can be empty if there are no space + * content states defined in the space or if space content states are disabled in the space. All spaces start with 4 + * default space content states, and this can be modified in the UI under space settings. + */ + spaceContentStates: z.array(ContentStateSchema), + /** + * Custom content states that can be used by the user on the content of this call. This list can be empty if there + * are no custom content states defined by the user or if custom content states are disabled in the space of the + * content. This will at most have 3 of the most recently published content states. Only the calling user has access + * to place these states on content, but all users can see these states once they are placed. + */ + customContentStates: z.array(ContentStateSchema), +}); + +export type AvailableContentStates = z.infer; diff --git a/src/v1/models/blueprintTemplate.ts b/src/v1/models/blueprintTemplate.ts new file mode 100644 index 00000000..33874fd0 --- /dev/null +++ b/src/v1/models/blueprintTemplate.ts @@ -0,0 +1,27 @@ +import { z } from 'zod'; +import { apiObject } from '#/core'; +import { LabelSchema } from './label'; +import { ContentTemplateBodySchema } from './contentTemplateBody'; +import { GenericLinksSchema } from './genericLinks'; + +export const BlueprintTemplateSchema = apiObject({ + templateId: z.string(), + originalTemplate: apiObject({ + pluginKey: z.string(), + moduleKey: z.string(), + }), + referencingBlueprint: z.string(), + name: z.string(), + description: z.string(), + space: z.record(z.string(), z.any()).optional(), + labels: z.array(LabelSchema), + templateType: z.string(), + editorVersion: z.string().optional(), + body: ContentTemplateBodySchema.optional(), + _expandable: apiObject({ + body: z.string().optional(), + }).optional(), + _links: GenericLinksSchema, +}); + +export type BlueprintTemplate = z.infer; diff --git a/src/v1/models/blueprintTemplateArray.ts b/src/v1/models/blueprintTemplateArray.ts new file mode 100644 index 00000000..80ae2db9 --- /dev/null +++ b/src/v1/models/blueprintTemplateArray.ts @@ -0,0 +1,14 @@ +import { z } from 'zod'; +import { apiObject } from '#/core'; +import { BlueprintTemplateSchema } from './blueprintTemplate'; +import { GenericLinksSchema } from './genericLinks'; + +export const BlueprintTemplateArraySchema = apiObject({ + results: z.array(BlueprintTemplateSchema), + start: z.number(), + limit: z.number(), + size: z.number(), + _links: GenericLinksSchema, +}); + +export type BlueprintTemplateArray = z.infer; diff --git a/src/v1/models/breadcrumb.ts b/src/v1/models/breadcrumb.ts new file mode 100644 index 00000000..95e4bec3 --- /dev/null +++ b/src/v1/models/breadcrumb.ts @@ -0,0 +1,10 @@ +import { z } from 'zod'; +import { apiObject } from '#/core'; + +export const BreadcrumbSchema = apiObject({ + label: z.string(), + url: z.string(), + separator: z.string(), +}); + +export type Breadcrumb = z.infer; diff --git a/src/v1/models/bulkContentBodyConversionInput.ts b/src/v1/models/bulkContentBodyConversionInput.ts new file mode 100644 index 00000000..7af19a47 --- /dev/null +++ b/src/v1/models/bulkContentBodyConversionInput.ts @@ -0,0 +1,9 @@ +import { z } from 'zod'; +import { apiObject } from '#/core'; +import { ContentBodyConversionInputSchema } from './contentBodyConversionInput'; + +export const BulkContentBodyConversionInputSchema = apiObject({ + conversionInputs: z.array(ContentBodyConversionInputSchema).optional(), +}); + +export type BulkContentBodyConversionInput = z.infer; diff --git a/src/v1/models/bulkUserLookup.ts b/src/v1/models/bulkUserLookup.ts new file mode 100644 index 00000000..1615a101 --- /dev/null +++ b/src/v1/models/bulkUserLookup.ts @@ -0,0 +1,43 @@ +import { z } from 'zod'; +import { apiObject } from '#/core'; +import { GenericUserNameSchema } from './genericUserName'; +import { GenericUserKeySchema } from './genericUserKey'; +import { GenericAccountIdSchema } from './genericAccountId'; +import { IconSchema } from './icon'; +import { OperationCheckResultSchema } from './operationCheckResult'; +import { UserDetailsSchema } from './userDetails'; +import { SpaceSchema } from './space'; +import { GenericLinksSchema } from './genericLinks'; + +export const BulkUserLookupSchema = apiObject({ + type: z.enum(['known', 'unknown', 'anonymous', 'user']), + username: GenericUserNameSchema.optional(), + userKey: GenericUserKeySchema.optional(), + accountId: GenericAccountIdSchema, + /** The account type of the user, may return empty string if unavailable. */ + accountType: z.string(), + /** The email address of the user. Depending on the user's privacy setting, this may return an empty string. */ + email: z.string(), + /** The public name or nickname of the user. Will always contain a value. */ + publicName: z.string(), + profilePicture: IconSchema, + /** The displays name of the user. Depending on the user's privacy setting, this may be the same as publicName. */ + displayName: z.string(), + /** This displays user time zone. Depending on the user's privacy setting, this may return null. */ + timeZone: z.string().nullish(), + /** This is deprecated. Use `isGuest` instead to find out whether the user is a guest user. */ + isExternalCollaborator: z.boolean().optional(), + /** Whether the user is a guest user */ + isGuest: z.boolean().optional(), + operations: z.array(OperationCheckResultSchema).optional(), + details: UserDetailsSchema.optional(), + personalSpace: SpaceSchema.optional(), + _expandable: apiObject({ + operations: z.string().optional(), + details: z.string().optional(), + personalSpace: z.string().optional(), + }), + _links: GenericLinksSchema, +}); + +export type BulkUserLookup = z.infer; diff --git a/src/v1/models/bulkUserLookupArray.ts b/src/v1/models/bulkUserLookupArray.ts new file mode 100644 index 00000000..ae2bba2a --- /dev/null +++ b/src/v1/models/bulkUserLookupArray.ts @@ -0,0 +1,14 @@ +import { z } from 'zod'; +import { apiObject } from '#/core'; +import { BulkUserLookupSchema } from './bulkUserLookup'; +import { GenericLinksSchema } from './genericLinks'; + +export const BulkUserLookupArraySchema = apiObject({ + results: z.array(BulkUserLookupSchema), + start: z.number(), + limit: z.number(), + size: z.number(), + _links: GenericLinksSchema, +}); + +export type BulkUserLookupArray = z.infer; diff --git a/src/v1/models/buttonLookAndFeel.ts b/src/v1/models/buttonLookAndFeel.ts new file mode 100644 index 00000000..5127bbf1 --- /dev/null +++ b/src/v1/models/buttonLookAndFeel.ts @@ -0,0 +1,9 @@ +import { z } from 'zod'; +import { apiObject } from '#/core'; + +export const ButtonLookAndFeelSchema = apiObject({ + backgroundColor: z.string(), + color: z.string(), +}); + +export type ButtonLookAndFeel = z.infer; diff --git a/src/v1/models/changedValue.ts b/src/v1/models/changedValue.ts new file mode 100644 index 00000000..bc874c40 --- /dev/null +++ b/src/v1/models/changedValue.ts @@ -0,0 +1,12 @@ +import { z } from 'zod'; +import { apiObject } from '#/core'; + +export const ChangedValueSchema = apiObject({ + name: z.string(), + oldValue: z.string(), + hiddenOldValue: z.string().optional(), + newValue: z.string(), + hiddenNewValue: z.string().optional(), +}); + +export type ChangedValue = z.infer; diff --git a/src/v1/models/connectModule.ts b/src/v1/models/connectModule.ts new file mode 100644 index 00000000..1c5d1190 --- /dev/null +++ b/src/v1/models/connectModule.ts @@ -0,0 +1,10 @@ +import type { z } from 'zod'; +import { apiObject } from '#/core'; +/** + * A [Connect module](https://developer.atlassian.com/cloud/confluence/modules/admin-page/) in the same format as in + * the* [app descriptor](https://developer.atlassian.com/cloud/confluence/app-descriptor/). + */ + +export const ConnectModuleSchema = apiObject({}); + +export type ConnectModule = z.infer; diff --git a/src/v1/models/connectModules.ts b/src/v1/models/connectModules.ts new file mode 100644 index 00000000..c3426e56 --- /dev/null +++ b/src/v1/models/connectModules.ts @@ -0,0 +1,13 @@ +import { z } from 'zod'; +import { apiObject } from '#/core'; +import { ConnectModuleSchema } from './connectModule'; + +export const ConnectModulesSchema = apiObject({ + /** + * A list of app modules in the same format as the `modules` property in the [app + * descriptor](https://developer.atlassian.com/cloud/confluence/app-descriptor/). + */ + modules: z.array(ConnectModuleSchema), +}); + +export type ConnectModules = z.infer; diff --git a/src/v1/models/container.ts b/src/v1/models/container.ts new file mode 100644 index 00000000..2699fd0f --- /dev/null +++ b/src/v1/models/container.ts @@ -0,0 +1,10 @@ +import type { z } from 'zod'; +import { apiObject } from '#/core'; +/** + * Container for content. This can be either a space (containing a page or blogpost)* or a page/blog post (containing an + * attachment or comment) + */ + +export const ContainerSchema = apiObject({}); + +export type Container = z.infer; diff --git a/src/v1/models/containerLookAndFeel.ts b/src/v1/models/containerLookAndFeel.ts new file mode 100644 index 00000000..0f030857 --- /dev/null +++ b/src/v1/models/containerLookAndFeel.ts @@ -0,0 +1,19 @@ +import { z } from 'zod'; +import { apiObject } from '#/core'; + +export const ContainerLookAndFeelSchema = apiObject({ + background: z.string(), + backgroundAttachment: z.string().nullish(), + backgroundBlendMode: z.string().nullish(), + backgroundClip: z.string().nullish(), + backgroundColor: z.string().nullable(), + backgroundImage: z.string().nullable(), + backgroundOrigin: z.string().nullish(), + backgroundPosition: z.string().nullish(), + backgroundRepeat: z.string().nullish(), + backgroundSize: z.string().nullable(), + padding: z.string(), + borderRadius: z.string(), +}); + +export type ContainerLookAndFeel = z.infer; diff --git a/src/v1/models/containerSummary.ts b/src/v1/models/containerSummary.ts new file mode 100644 index 00000000..b6e61cd9 --- /dev/null +++ b/src/v1/models/containerSummary.ts @@ -0,0 +1,9 @@ +import { z } from 'zod'; +import { apiObject } from '#/core'; + +export const ContainerSummarySchema = apiObject({ + title: z.string(), + displayUrl: z.string(), +}); + +export type ContainerSummary = z.infer; diff --git a/src/v1/models/content.ts b/src/v1/models/content.ts new file mode 100644 index 00000000..e15f99b4 --- /dev/null +++ b/src/v1/models/content.ts @@ -0,0 +1,161 @@ +import { z } from 'zod'; +import { apiObject } from '#/core'; +import { SpaceSchema, type Space } from './space'; +import { ContentHistorySchema, type ContentHistory } from './contentHistory'; +import { VersionSchema, type Version } from './version'; +import { OperationCheckResultSchema, type OperationCheckResult } from './operationCheckResult'; +import { ContentChildrenSchema, type ContentChildren } from './contentChildren'; +import { ContentChildTypeSchema, type ContentChildType } from './contentChildType'; +import { ContainerSchema, type Container } from './container'; +import { ContentBodySchema, type ContentBody } from './contentBody'; +import { ContentRestrictionSchema, type ContentRestriction } from './contentRestriction'; +import { GenericLinksSchema, type GenericLinks } from './genericLinks'; +import { ContentMetadataSchema, type ContentMetadata } from './contentMetadata'; + +export type Content = { + id?: string; + type: string; + status: string; + title?: string; + space?: Space; + history?: ContentHistory; + version?: Version; + ancestors?: Content[] | null; + operations?: OperationCheckResult[]; + children?: ContentChildren; + childTypes?: ContentChildType; + descendants?: ContentChildren; + container?: Container; + body?: { + view?: ContentBody; + export_view?: ContentBody; + styled_view?: ContentBody; + storage?: ContentBody; + wiki?: ContentBody; + editor?: ContentBody; + editor2?: ContentBody; + anonymous_export_view?: ContentBody; + atlas_doc_format?: ContentBody; + dynamic?: ContentBody; + raw?: ContentBody; + _expandable?: { + editor?: string; + view?: string; + export_view?: string; + styled_view?: string; + storage?: string; + editor2?: string; + anonymous_export_view?: string; + atlas_doc_format?: string; + wiki?: string; + dynamic?: string; + raw?: string; + }; + }; + restrictions?: { + read?: ContentRestriction; + update?: ContentRestriction; + _expandable?: { + read?: string; + update?: string; + }; + _links?: GenericLinks; + }; + metadata?: ContentMetadata; + macroRenderedOutput?: Record; + extensions?: Record; + _expandable?: { + childTypes?: string; + container?: string; + metadata?: string; + operations?: string; + children?: string; + restrictions?: string; + history?: string; + ancestors?: string; + body?: string; + version?: string; + descendants?: string; + space?: string; + extensions?: string; + schedulePublishDate?: string; + schedulePublishInfo?: string; + macroRenderedOutput?: string; + }; + _links?: GenericLinks; +}; +/** Base object for all content types. */ + +export const ContentSchema: z.ZodType = apiObject({ + id: z.string().optional(), + /** Can be "page", "blogpost", "attachment" or "content" */ + type: z.string(), + status: z.string(), + title: z.string().optional(), + space: z.lazy(() => SpaceSchema).optional(), + history: z.lazy(() => ContentHistorySchema).optional(), + version: z.lazy(() => VersionSchema).optional(), + ancestors: z.array(z.lazy(() => ContentSchema)).nullish(), + operations: z.array(OperationCheckResultSchema).optional(), + children: z.lazy(() => ContentChildrenSchema).optional(), + childTypes: ContentChildTypeSchema.optional(), + descendants: z.lazy(() => ContentChildrenSchema).optional(), + container: ContainerSchema.optional(), + body: apiObject({ + view: ContentBodySchema.optional(), + export_view: ContentBodySchema.optional(), + styled_view: ContentBodySchema.optional(), + storage: ContentBodySchema.optional(), + wiki: ContentBodySchema.optional(), + editor: ContentBodySchema.optional(), + editor2: ContentBodySchema.optional(), + anonymous_export_view: ContentBodySchema.optional(), + atlas_doc_format: ContentBodySchema.optional(), + dynamic: ContentBodySchema.optional(), + raw: ContentBodySchema.optional(), + _expandable: apiObject({ + editor: z.string().optional(), + view: z.string().optional(), + export_view: z.string().optional(), + styled_view: z.string().optional(), + storage: z.string().optional(), + editor2: z.string().optional(), + anonymous_export_view: z.string().optional(), + atlas_doc_format: z.string().optional(), + wiki: z.string().optional(), + dynamic: z.string().optional(), + raw: z.string().optional(), + }).optional(), + }).optional(), + restrictions: apiObject({ + read: z.lazy(() => ContentRestrictionSchema).optional(), + update: z.lazy(() => ContentRestrictionSchema).optional(), + _expandable: apiObject({ + read: z.string().optional(), + update: z.string().optional(), + }).optional(), + _links: GenericLinksSchema.optional(), + }).optional(), + metadata: z.lazy(() => ContentMetadataSchema).optional(), + macroRenderedOutput: z.record(z.string(), z.any()).optional(), + extensions: z.record(z.string(), z.any()).optional(), + _expandable: apiObject({ + childTypes: z.string().optional(), + container: z.string().optional(), + metadata: z.string().optional(), + operations: z.string().optional(), + children: z.string().optional(), + restrictions: z.string().optional(), + history: z.string().optional(), + ancestors: z.string().optional(), + body: z.string().optional(), + version: z.string().optional(), + descendants: z.string().optional(), + space: z.string().optional(), + extensions: z.string().optional(), + schedulePublishDate: z.string().optional(), + schedulePublishInfo: z.string().optional(), + macroRenderedOutput: z.string().optional(), + }).optional(), + _links: GenericLinksSchema.optional(), +}); diff --git a/src/v1/models/contentArray.ts b/src/v1/models/contentArray.ts new file mode 100644 index 00000000..f5af2d17 --- /dev/null +++ b/src/v1/models/contentArray.ts @@ -0,0 +1,20 @@ +import { z } from 'zod'; +import { apiObject } from '#/core'; +import { ContentSchema, type Content } from './content'; +import { GenericLinksSchema, type GenericLinks } from './genericLinks'; + +export type ContentArray = { + results: Content[]; + start?: number; + limit?: number; + size: number; + _links: GenericLinks; +}; + +export const ContentArraySchema: z.ZodType = apiObject({ + results: z.array(z.lazy(() => ContentSchema)), + start: z.number().optional(), + limit: z.number().optional(), + size: z.number(), + _links: GenericLinksSchema, +}); diff --git a/src/v1/models/contentBlogpost.ts b/src/v1/models/contentBlogpost.ts new file mode 100644 index 00000000..cfdea140 --- /dev/null +++ b/src/v1/models/contentBlogpost.ts @@ -0,0 +1,7 @@ +import type { z } from 'zod'; +import { apiObject } from '#/core'; +/** Representation of a blogpost (content) */ + +export const ContentBlogpostSchema = apiObject({}); + +export type ContentBlogpost = z.infer; diff --git a/src/v1/models/contentBlueprintDraft.ts b/src/v1/models/contentBlueprintDraft.ts new file mode 100644 index 00000000..2042078b --- /dev/null +++ b/src/v1/models/contentBlueprintDraft.ts @@ -0,0 +1,38 @@ +import { z } from 'zod'; +import { apiObject } from '#/core'; + +export const ContentBlueprintDraftSchema = apiObject({ + /** The version for the new content. */ + version: apiObject({ + /** The version number. Set this to `1`. */ + number: z.number(), + }), + /** The title of the content. If you don't want to change the title, set this to the current title of the draft. */ + title: z.string().max(255, 'title must be at most 255 characters'), + /** The type of content. Set this to `page`. */ + type: z.enum(['page']), + /** The status of the content. Set this to `current` or omit it altogether. */ + status: z.enum(['current']).optional(), + /** The space for the content. */ + space: apiObject({ + /** The key of the space */ + key: z.string(), + }).optional(), + /** + * The new ancestor (i.e. parent page) for the content. If you have specified an ancestor, you must also specify a + * `space` property in the request body for the space that the ancestor is in. + * + * Note, if you specify more than one ancestor, the last ID in the array will be selected as the parent page for the + * content. + */ + ancestors: z + .array( + apiObject({ + /** The content ID of the ancestor. */ + id: z.string(), + }), + ) + .nullish(), +}); + +export type ContentBlueprintDraft = z.infer; diff --git a/src/v1/models/contentBody.ts b/src/v1/models/contentBody.ts new file mode 100644 index 00000000..9c09b81f --- /dev/null +++ b/src/v1/models/contentBody.ts @@ -0,0 +1,39 @@ +import { z } from 'zod'; +import { apiObject } from '#/core'; +import { EmbeddedContentSchema } from './embeddedContent'; +import { WebResourceDependenciesSchema } from './webResourceDependencies'; +import { GenericLinksSchema } from './genericLinks'; + +export const ContentBodySchema = apiObject({ + value: z.string(), + representation: z.enum([ + 'view', + 'export_view', + 'styled_view', + 'storage', + 'editor', + 'editor2', + 'anonymous_export_view', + 'wiki', + 'atlas_doc_format', + 'raw', + ]), + embeddedContent: z.array(EmbeddedContentSchema).optional(), + webresource: WebResourceDependenciesSchema.optional(), + mediaToken: apiObject({ + collectionIds: z.array(z.string()).optional(), + contentId: z.string().optional(), + expiryDateTime: z.string().optional(), + fileIds: z.array(z.string()).optional(), + token: z.string().optional(), + }).optional(), + _expandable: apiObject({ + content: z.string().optional(), + embeddedContent: z.string().optional(), + webresource: z.string().optional(), + mediaToken: z.string().optional(), + }).optional(), + _links: GenericLinksSchema.optional(), +}); + +export type ContentBody = z.infer; diff --git a/src/v1/models/contentBodyConversionInput.ts b/src/v1/models/contentBodyConversionInput.ts new file mode 100644 index 00000000..a08e6599 --- /dev/null +++ b/src/v1/models/contentBodyConversionInput.ts @@ -0,0 +1,68 @@ +import { z } from 'zod'; +import { apiObject } from '#/core'; +import { ContentBodyCreateSchema } from './contentBodyCreate'; + +export const ContentBodyConversionInputSchema = apiObject({ + /** The name of the target format for the content body conversion. */ + to: z.string(), + /** + * Controls whether conversion results are cached and reused for identical requests. + * + * - `false`: Each request creates a new conversion task, even if an identical request was made previously. + * - `true`: Enables caching behavior for identical requests from the same user. + * + * - If no cached result exists, a new conversion task is created + * - If a cached result exists, the existing task is marked as RERUNNING and will complete with status COMPLETED + * - Returns the same task ID for identical requests, allowing you to retrieve the cached result + */ + allowCache: z.boolean().optional(), + /** + * The space key used for resolving embedded content (page includes, files, and links) in the content body. For + * example, if the source content contains the link `` + * and the `spaceKeyContext=TEST` parameter is provided, then the link will be converted into a link to the "Example + * page" page in the "TEST" space. + */ + spaceKeyContext: z.string().optional(), + /** + * The content ID used to find the space for resolving embedded content (page includes, files, and links) in the + * content body. For example, if the source content contains the link `` and the `contentIdContext=123` parameter is provided, then the link will be converted into a + * link to the "Example page" page in the same space that has the content with ID=123. Note that `spaceKeyContext` + * will be ignored if this parameter is provided. + */ + contentIdContext: z.string().optional(), + /** + * Mode used for rendering embedded content, such as attachments. - `current` renders the embedded content using the + * latest version. - `version-at-save` renders the embedded content using the version at the time of save. + */ + embeddedContentRender: z.enum(['current', 'version-at-save']).optional(), + /** + * A multi-value, comma-separated parameter indicating which properties of the content to expand and populate. + * Expands are dependent on the `to` conversion format and may be irrelevant for certain conversions (e.g. + * `macroRenderedOutput` is redundant when converting to `view` format). + * + * If rendering to `view` format, and the body content being converted includes arbitrary nested content (such as + * macros); then it is necessary to include webresource expands in the request. Webresources for content body are + * the batched JS and CSS dependencies for any nested dynamic content (i.e. macros). + * + * - `embeddedContent` returns metadata for nested content (e.g. page included using page include macro) + * - `mediaToken` returns JWT token for retrieving attachment data from Media API + * - `macroRenderedOutput` additionally converts body to view format + * - `webresource.superbatch.uris.js` returns all common JS dependencies as static URLs + * - `webresource.superbatch.uris.css` returns all common CSS dependencies as static URLs + * - `webresource.superbatch.uris.all` returns all common dependencies as static URLs + * - `webresource.superbatch.tags.all` returns all common JS dependencies as html `