confluence-api-doc

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Confluence API Doc Sync

Confluence API文档同步

Sync API documentation from a single Markdown file to Confluence — one API per page. When a Markdown file documents multiple APIs, split it into individual Confluence pages so each API endpoint has its own dedicated page.
Uses
acli
for authentication verification and page reading (to get current version), and Confluence REST API via
curl
for page updates.
将单个Markdown文件中的API文档同步到Confluence —— 每页对应一个API。如果单个Markdown文件记录了多个API,会将其拆分到独立的Confluence页面,让每个API端点都有专属的页面。
使用
acli
完成身份认证校验和页面读取(获取当前版本),通过
curl
调用Confluence REST API完成页面更新。

Core Principle: 1 API = 1 Confluence Page

核心原则:1个API = 1个Confluence页面

A single API doc file typically documents many endpoints grouped by domain. This skill splits that file into a Confluence page tree:
Parent Folder/Page
├── 2. Consent Management APIs          ← domain group page (H2 intro text only)
│   ├── 2.1 Accept Consent              ← individual API page (full H3 content)
│   ├── 2.2 Revoke Consents             ← individual API page
│   └── 2.3 Get Consents by Citizen ID  ← individual API page
├── 3. Purpose Management APIs          ← domain group page
│   ├── 3.1 Create Purpose              ← individual API page
│   └── 3.2 Get All Purposes            ← individual API page
├── 12. Error Responses                 ← standalone page (H2 with no H3 children)
└── 13. Changelog                       ← standalone page
Each H3 section (
### X.Y API Name
) becomes exactly one Confluence page containing everything from that H3 heading down to the next H3 or H2 heading.
单个API文档文件通常会按领域分组记录多个端点,本skill会将该文件拆分为Confluence页面树:
Parent Folder/Page
├── 2. Consent Management APIs          ← 领域分组页面(仅包含H2介绍文本)
│   ├── 2.1 Accept Consent              ← 独立API页面(包含完整H3内容)
│   ├── 2.2 Revoke Consents             ← 独立API页面
│   └── 2.3 Get Consents by Citizen ID  ← 独立API页面
├── 3. Purpose Management APIs          ← 领域分组页面
│   ├── 3.1 Create Purpose              ← 独立API页面
│   └── 3.2 Get All Purposes            ← 独立API页面
├── 12. Error Responses                 ← 独立页面(H2无下属H3内容)
└── 13. Changelog                       ← 独立页面
每个H3章节(
### X.Y API名称
)会生成一个独立的Confluence页面,内容包含从该H3标题开始到下一个H3或H2标题之前的所有内容。

Step 1: Gather Required Information

步骤1:收集必要信息

Ask the user for the following (if not already provided):
  1. API doc file path — e.g.,
    docs/api-doc.md
    (relative to project root, or absolute)
  2. Parent page URL — the Confluence page/folder under which API doc pages live (or will be created), e.g.,
    https://company.atlassian.net/wiki/spaces/PROJ/pages/123456789/API+Reference
    or a folder URL like
    https://company.atlassian.net/wiki/spaces/PROJ/folder/123456789
Extract the page ID directly from the URL (the numeric segment, e.g.,
123456789
).
Do NOT ask for Confluence URL, email, or API token — those are resolved automatically in the next step.
如果用户尚未提供以下信息,向用户询问:
  1. API文档文件路径 —— 例如
    docs/api-doc.md
    (相对项目根目录的路径,或绝对路径)
  2. 父页面URL —— API文档页面存放(或即将创建)的Confluence页面/文件夹地址,例如
    https://company.atlassian.net/wiki/spaces/PROJ/pages/123456789/API+Reference
    ,或者文件夹URL如
    https://company.atlassian.net/wiki/spaces/PROJ/folder/123456789
直接从URL中提取页面ID(数字片段,例如
123456789
)。
不要询问用户Confluence URL、邮箱或API token —— 这些信息会在下一步自动获取。

Step 2: Verify Authentication and Resolve Credentials

步骤2:校验身份认证并获取凭证

bash
acli auth status
If not authenticated or acli not found:
From the output, extract:
  • CONFLUENCE_URL
    Site:
    field prefixed with
    https://
    , e.g.,
    company.atlassian.net
    https://company.atlassian.net
  • EMAIL
    Email:
    field, e.g.,
    user@company.com
Why REST API for writes?
acli confluence page
currently only supports
view
. For page create/update we use Confluence REST API via
curl
. URL and email come from
acli auth status
; only the API token needs to be resolved (at write time).
bash
acli auth status
如果未完成认证或找不到acli:
从输出结果中提取:
  • CONFLUENCE_URL ——
    Site:
    字段前缀加上
    https://
    ,例如
    company.atlassian.net
    https://company.atlassian.net
  • EMAIL ——
    Email:
    字段,例如
    user@company.com
为什么写入操作要用REST API?
acli confluence page
目前仅支持
view
操作。创建/更新页面需要通过
curl
调用Confluence REST API。URL和邮箱从
acli auth status
获取,仅API token需要在写入时获取。

Step 3: Read, Parse, and Split into Pages

步骤3:读取、解析并拆分为页面

Read the API doc file and split it into individual pages. The Markdown follows a two-level heading structure:
  • H2 (
    ## N. Domain Name
    )
    — domain group header (e.g.,
    ## 2. Consent Management APIs
    )
  • H3 (
    ### N.M API Name
    )
    — individual API endpoint (e.g.,
    ### 2.1 Accept Consent
    )
读取API文档文件并拆分为独立页面。Markdown遵循两级标题结构:
  • H2 (
    ## N. 领域名称
    )
    —— 领域分组标题(例如
    ## 2. Consent Management APIs
  • H3 (
    ### N.M API名称
    )
    —— 独立API端点(例如
    ### 2.1 Accept Consent

Parsing Rules

解析规则

  1. Scan all H2 and H3 headings in the file
  2. Classify each H2 section into one of:
    • Domain group — has H3 children → becomes a parent page in Confluence
    • Standalone page — has no H3 children (e.g., Error Responses, Changelog) → becomes a leaf page
    • Skip — meta sections like
      Overview
      ,
      Table of Contents
      that don't need their own page (or optionally create a single overview page)
  3. Extract content per H3 — each H3 section includes everything from the
    ### X.Y
    heading down to (but not including) the next
    ###
    or
    ##
    heading. This is one API page's content.
  4. Domain group intro — text between an H2 heading and its first H3 child becomes the domain group page's content (often just a brief intro paragraph, or empty).
  1. 扫描文件中所有H2和H3标题
  2. 将每个H2章节归类为以下类型之一
    • 领域分组 —— 包含H3子章节 → 成为Confluence中的父页面
    • 独立页面 —— 不包含H3子章节(例如错误响应、更新日志) → 成为叶子页面
    • 跳过 —— 不需要单独生成页面的元章节,如
      概览
      目录
      (也可选择生成单个概览页面)
  3. 提取每个H3的内容 —— 每个H3章节包含从
    ### X.Y
    标题开始到下一个
    ###
    ##
    标题(不含)之前的所有内容,对应一个API页面的内容。
  4. 领域分组介绍 —— H2标题到其第一个H3子章节之间的文本作为领域分组页面的内容(通常只是简短的介绍段落,或为空)。

Content Extraction Example

内容提取示例

Given this Markdown structure:
markdown
undefined
给定以下Markdown结构:
markdown
undefined

2. Consent Management APIs

2. Consent Management APIs

Consent APIs for managing personal data consent.
Consent APIs for managing personal data consent.

2.1 Accept Consent

2.1 Accept Consent

  • Method:
    POST
  • Path:
    /api/v1/consents/accept
    ...request/response tables and examples...
  • Method:
    POST
  • Path:
    /api/v1/consents/accept
    ...请求/响应表格和示例...

2.2 Revoke Consents

2.2 Revoke Consents

  • Method:
    POST
  • Path:
    /api/v1/consents/revoke
    ...

This produces:
- **Page "2. Consent Management APIs"** → content: `"Consent APIs for managing personal data consent."` (parent page)
- **Page "2.1 Accept Consent"** → content: everything from `### 2.1` to just before `### 2.2` (child page)
- **Page "2.2 Revoke Consents"** → content: everything from `### 2.2` to next heading (child page)
  • Method:
    POST
  • Path:
    /api/v1/consents/revoke
    ...

会生成以下页面:
- **页面「2. Consent Management APIs」** → 内容:`"Consent APIs for managing personal data consent."`(父页面)
- **页面「2.1 Accept Consent」** → 内容:从`### 2.1`到`### 2.2`之前的所有内容(子页面)
- **页面「2.2 Revoke Consents」** → 内容:从`### 2.2`到下一个标题之前的所有内容(子页面)

Summary Output

摘要输出

After scanning, show the user a structured summary:
Found N domain groups, M individual APIs, K standalone pages:

  2. Consent Management APIs (5 APIs)
     2.1 Accept Consent
     2.2 Revoke Consents
     2.3 Get Consents by Citizen ID
     2.4 Get Consent History
     2.5 Get Consent by ID
  3. Purpose Management APIs (11 APIs)
     3.1 Create Purpose
     3.2 Get All Purposes
     ...
  12. Error Responses (standalone)
  13. Changelog (standalone)

Total pages to create/update: N (domain groups) + M (APIs) + K (standalone) = T pages
Ask the user to confirm or specify which sections to sync (all, specific domains, or specific APIs).
扫描完成后,向用户展示结构化摘要:
找到N个领域分组、M个独立API、K个独立页面:

  2. Consent Management APIs (5个API)
     2.1 Accept Consent
     2.2 Revoke Consents
     2.3 Get Consents by Citizen ID
     2.4 Get Consent History
     2.5 Get Consent by ID
  3. Purpose Management APIs (11个API)
     3.1 Create Purpose
     3.2 Get All Purposes
     ...
  12. Error Responses (独立页面)
  13. Changelog (独立页面)

总计需要创建/更新页面数:N(领域分组) + M(API) + K(独立页面) = T个页面
请用户确认或指定需要同步的章节(全部、特定领域或特定API)。

Step 4: Map Sections to Confluence Page Hierarchy

步骤4:将章节映射到Confluence页面层级

The page structure in Confluence mirrors the document structure:
Parent page (provided by user)
├── Domain Group pages (H2 with children) ← first-level children
│   └── Individual API pages (H3)        ← second-level children
└── Standalone pages (H2 without H3)     ← first-level children
Confluence中的页面结构与文档结构保持一致:
用户提供的父页面
├── 领域分组页面(包含子项的H2) ← 一级子页面
│   └── 独立API页面(H3)        ← 二级子页面
└── 独立页面(无H3子项的H2)     ← 一级子页面

Discover Existing Pages

查找现有页面

First, fetch all children (and grandchildren) under the parent page to find existing pages:
bash
undefined
首先获取父页面下的所有子页面(以及孙页面),查找已存在的页面:
bash
undefined

Get direct children of parent page

获取父页面的直接子页面

curl -s "${CONFLUENCE_URL}/wiki/rest/api/content/${PARENT_PAGE_ID}?expand=space,children.page"
-u "${EMAIL}:${API_TOKEN}"

From the response extract:
- `space.key` → save as `SPACE_KEY` (needed for creating new pages)
- `children.page.results[]` → list of `{id, title}` for direct children

For each direct child that looks like a domain group, also fetch its children:
```bash
curl -s "${CONFLUENCE_URL}/wiki/rest/api/content/${DOMAIN_GROUP_PAGE_ID}/child/page" \
  -u "${EMAIL}:${API_TOKEN}"
curl -s "${CONFLUENCE_URL}/wiki/rest/api/content/${PARENT_PAGE_ID}?expand=space,children.page"
-u "${EMAIL}:${API_TOKEN}"

从响应中提取:
- `space.key` → 保存为`SPACE_KEY`(创建新页面需要)
- `children.page.results[]` → 直接子页面的`{id, title}`列表

对于每个属于领域分组的直接子页面,同时获取其下属子页面:
```bash
curl -s "${CONFLUENCE_URL}/wiki/rest/api/content/${DOMAIN_GROUP_PAGE_ID}/child/page" \
  -u "${EMAIL}:${API_TOKEN}"

Build the Mapping

构建映射关系

Match existing page titles against parsed section titles to build the mapping:
SectionTypeMatched Page IDAction
2. Consent Management APIsDomain group456789Update
2.1 Accept ConsentAPI page567890Update
2.2 Revoke ConsentsAPI pageCreate (under 456789)
3. Purpose Management APIsDomain groupCreate (under parent)
3.1 Create PurposeAPI pageCreate (under new domain group page)
Important ordering: When creating new pages, domain group pages must be created before their child API pages (because child pages need the parent's page ID as ancestor).
将现有页面标题与解析得到的章节标题进行匹配,构建映射关系:
章节类型匹配到的页面ID操作
2. Consent Management APIs领域分组456789更新
2.1 Accept ConsentAPI页面567890更新
2.2 Revoke ConsentsAPI页面创建(隶属于456789)
3. Purpose Management APIs领域分组创建(隶属于父页面)
3.1 Create PurposeAPI页面创建(隶属于新的领域分组页面)
重要排序规则:创建新页面时,必须先创建领域分组页面,再创建其下属的API子页面(因为子页面需要父页面的ID作为祖先参数)。

Matching Strategy

匹配策略

  • Match by title similarity (case-insensitive, ignore leading numbers like "2.1")
  • If ambiguous, show the user and ask them to confirm the mapping
  • For unmatched sections → mark as "Create new"
  • 通过标题相似度匹配(不区分大小写,忽略「2.1」这类开头数字)
  • 如果匹配结果不明确,向用户展示并请用户确认映射关系
  • 未匹配到的章节 → 标记为「新建」

Step 5: Get Current Page Versions

步骤5:获取当前页面版本

For each page in the mapping, fetch its current version number (required for updates):
bash
acli confluence page view --id <PAGE_ID> --include-version --json
Extract
version.number
from the JSON output. Store as
CURRENT_VERSION
per page.
对于映射关系中的每个页面,获取其当前版本号(更新操作需要):
bash
acli confluence page view --id <PAGE_ID> --include-version --json
从JSON输出中提取
version.number
,按页面保存为
CURRENT_VERSION

Step 6: Convert Markdown to Confluence Storage Format

步骤6:将Markdown转换为Confluence存储格式

For each section, convert the Markdown content to Confluence storage format (XHTML-based):
MarkdownConfluence Storage
```lang\ncode\n```
<ac:structured-macro ac:name="code"><ac:parameter ac:name="language">lang</ac:parameter><ac:plain-text-body><![CDATA[code]]></ac:plain-text-body></ac:structured-macro>
**bold**
<strong>bold</strong>
*italic*
<em>italic</em>
[text](url)
<a href="url">text</a>
## Heading
<h2>Heading</h2>
| col | col |
table
<table><tbody><tr><td>...</td></tr></tbody></table>
For
js
,
javascript
,
sh
,
bash
,
json
,
yaml
code blocks, map to the Confluence language name accordingly (
bash
for
sh
,
javascript
for
js
).
将每个章节的Markdown内容转换为Confluence存储格式(基于XHTML):
MarkdownConfluence存储格式
```lang\ncode\n```
<ac:structured-macro ac:name="code"><ac:parameter ac:name="language">lang</ac:parameter><ac:plain-text-body><![CDATA[code]]></ac:plain-text-body></ac:structured-macro>
**bold**
<strong>bold</strong>
*italic*
<em>italic</em>
[text](url)
<a href="url">text</a>
## Heading
<h2>Heading</h2>
| col | col |
表格
<table><tbody><tr><td>...</td></tr></tbody></table>
对于
js
javascript
sh
bash
json
yaml
代码块,对应映射为Confluence支持的语言名称(
sh
映射为
bash
js
映射为
javascript
)。

Step 7: Sync Pages (Create + Update) via REST API

步骤7:通过REST API同步页面(创建+更新)

Before writing, resolve the API token:
bash
echo $CONFLUENCE_API_TOKEN
  • If set → use it silently, no need to ask
  • If empty → ask the user once:
    "ต้องการ API token สำหรับ write ผ่าน Confluence REST API (acli ยังไม่ support page write) — generate ได้ที่ https://id.atlassian.com/manage-profile/security/api-tokens"
Use
EMAIL
extracted from
acli auth status
in Step 2.
写入操作前,先获取API token:
bash
echo $CONFLUENCE_API_TOKEN
使用步骤2中从
acli auth status
提取的
EMAIL

Execution Order (critical for parent-child hierarchy)

执行顺序(对父子层级至关重要)

  1. First pass — Domain group pages: Create or update all H2 domain group pages as children of the parent page. This ensures parent page IDs exist before creating child API pages.
  2. Second pass — Individual API pages: Create or update all H3 API pages as children of their respective domain group pages.
  3. Third pass — Standalone pages: Create or update H2 pages that have no H3 children, as direct children of the parent page.
  1. 第一遍 —— 领域分组页面:创建或更新所有H2领域分组页面,作为父页面的子页面。确保创建子API页面前父页面ID已存在。
  2. 第二遍 —— 独立API页面:创建或更新所有H3 API页面,作为对应领域分组页面的子页面。
  3. 第三遍 —— 独立页面:创建或更新无H3子项的H2页面,作为父页面的直接子页面。

Creating a New Page

创建新页面

bash
curl -s -X POST \
  "${CONFLUENCE_URL}/wiki/rest/api/content" \
  -u "${EMAIL}:${API_TOKEN}" \
  -H "Content-Type: application/json" \
  -d "{
    \"type\": \"page\",
    \"title\": \"${SECTION_TITLE}\",
    \"ancestors\": [{\"id\": \"${ANCESTOR_PAGE_ID}\"}],
    \"space\": {\"key\": \"${SPACE_KEY}\"},
    \"body\": {
      \"storage\": {
        \"value\": \"${ESCAPED_HTML}\",
        \"representation\": \"storage\"
      }
    }
  }"
  • For domain group pages:
    ANCESTOR_PAGE_ID
    = user-provided parent page ID
  • For individual API pages:
    ANCESTOR_PAGE_ID
    = the domain group page ID (created in first pass)
  • For standalone pages:
    ANCESTOR_PAGE_ID
    = user-provided parent page ID
Extract
id
from the response to use as ancestor for child pages.
bash
curl -s -X POST \
  "${CONFLUENCE_URL}/wiki/rest/api/content" \
  -u "${EMAIL}:${API_TOKEN}" \
  -H "Content-Type: application/json" \
  -d "{
    \"type\": \"page\",
    \"title\": \"${SECTION_TITLE}\",
    \"ancestors\": [{\"id\": \"${ANCESTOR_PAGE_ID}\"}],
    \"space\": {\"key\": \"${SPACE_KEY}\"},
    \"body\": {
      \"storage\": {
        \"value\": \"${ESCAPED_HTML}\",
        \"representation\": \"storage\"
      }
    }
  }"
  • 领域分组页面:
    ANCESTOR_PAGE_ID
    = 用户提供的父页面ID
  • 独立API页面:
    ANCESTOR_PAGE_ID
    = 第一遍创建的领域分组页面ID
  • 独立页面:
    ANCESTOR_PAGE_ID
    = 用户提供的父页面ID
从响应中提取
id
,作为子页面的祖先参数使用。

Updating an Existing Page

更新现有页面

bash
curl -s -X PUT \
  "${CONFLUENCE_URL}/wiki/rest/api/content/${PAGE_ID}" \
  -u "${EMAIL}:${API_TOKEN}" \
  -H "Content-Type: application/json" \
  -d "{
    \"version\": {\"number\": $((CURRENT_VERSION + 1))},
    \"title\": \"${SECTION_TITLE}\",
    \"type\": \"page\",
    \"body\": {
      \"storage\": {
        \"value\": \"${ESCAPED_HTML}\",
        \"representation\": \"storage\"
      }
    }
  }"
Check HTTP status — 200 means success.
Content comparison tip: Before updating, compare normalized content (collapse whitespace) to skip pages with no real changes. This avoids unnecessary version bumps.
bash
curl -s -X PUT \
  "${CONFLUENCE_URL}/wiki/rest/api/content/${PAGE_ID}" \
  -u "${EMAIL}:${API_TOKEN}" \
  -H "Content-Type: application/json" \
  -d "{
    \"version\": {\"number\": $((CURRENT_VERSION + 1))},
    \"title\": \"${SECTION_TITLE}\",
    \"type\": \"page\",
    \"body\": {
      \"storage\": {
        \"value\": \"${ESCAPED_HTML}\",
        \"representation\": \"storage\"
      }
    }
  }"
检查HTTP状态码 —— 200表示成功。
内容对比提示:更新前对比标准化后的内容(折叠空白字符),跳过无实际变更的页面,避免不必要的版本升级。

Step 8: Report Results

步骤8:报告结果

Print a summary table after all operations:
| Section                    | Type           | Page ID    | Status                  |
|----------------------------|----------------|------------|-------------------------|
| 2. Consent Management APIs | Domain group   | 456789     | Updated (v3 → v4)       |
| 2.1 Accept Consent         | API page       | 567890     | Updated (v2 → v3)       |
| 2.2 Revoke Consents        | API page       | 678901     | Created                 |
| 2.3 Get Consents           | API page       | 567890     | Skipped (no changes)    |
| 12. Error Responses        | Standalone     | 789012     | Created                 |
| 3.1 Create Purpose         | API page       | —          | Failed (HTTP 401)       |
Total: N domain groups, M API pages updated, K created, J skipped, F failed.
所有操作完成后打印汇总表格:
| 章节                        | 类型           | 页面ID    | 状态                  |
|----------------------------|----------------|------------|-------------------------|
| 2. Consent Management APIs | 领域分组       | 456789     | 已更新 (v3 → v4)       |
| 2.1 Accept Consent         | API页面        | 567890     | 已更新 (v2 → v3)       |
| 2.2 Revoke Consents        | API页面        | 678901     | 已创建                 |
| 2.3 Get Consents           | API页面        | 567890     | 已跳过 (无变更)        |
| 12. Error Responses        | 独立页面       | 789012     | 已创建                 |
| 3.1 Create Purpose         | API页面        | —          | 失败 (HTTP 401)       |
总计:N个领域分组,M个API页面已更新,K个已创建,J个已跳过,F个失败。

Error Reference

错误参考

ScenarioAction
acli
not found
Install via
brew install atlassian/tap/acli
acli auth status
fails
Run
acli auth login
API doc file not foundRe-ask for correct file path
HTTP 401 on REST callCheck API token — re-check
$CONFLUENCE_API_TOKEN
or ask user
HTTP 404 on pageVerify page ID is correct; page may have been deleted
HTTP 409 version conflictRe-fetch version with acli and retry
Section title has no matchAsk user to manually provide page ID
场景处理方式
找不到
acli
通过
brew install atlassian/tap/acli
安装
acli auth status
执行失败
运行
acli auth login
找不到API文档文件重新询问正确的文件路径
REST调用返回HTTP 401检查API token —— 重新确认
$CONFLUENCE_API_TOKEN
或询问用户
页面请求返回HTTP 404验证页面ID是否正确,页面可能已被删除
HTTP 409版本冲突通过acli重新获取版本号并重试
章节标题无匹配结果请用户手动提供页面ID