HomeBrowseUpload
← Back to registry
// Skill profile

Confluence

name: confluence

by byungkyu · published 2026-03-22

邮件处理开发工具加密货币
Total installs
0
Stars
★ 0
Last updated
2026-03
// Install command
$ claw add gh:byungkyu/byungkyu-confluence-api
View on GitHub
// Full documentation

---

name: confluence

description: |

Confluence API integration with managed OAuth. Manage pages, spaces, blogposts, comments, and attachments.

Use this skill when users want to create, read, update, or delete Confluence content, manage spaces, or work with comments and attachments.

For other third party apps, use the api-gateway skill (https://clawhub.ai/byungkyu/api-gateway).

Requires network access and valid Maton API key.

metadata:

author: maton

version: "1.0"

clawdbot:

emoji: 🧠

homepage: "https://maton.ai"

requires:

env:

- MATON_API_KEY

---

# Confluence

Access the Confluence Cloud API with managed OAuth authentication. Manage pages, spaces, blogposts, comments, attachments, and properties.

Quick Start

# List pages in your Confluence site
python3 <<'EOF'
import urllib.request, os, json

# First get your Cloud ID
req = urllib.request.Request('https://gateway.maton.ai/confluence/oauth/token/accessible-resources')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
resources = json.load(urllib.request.urlopen(req))
cloud_id = resources[0]['id']

# Then list pages
req = urllib.request.Request(f'https://gateway.maton.ai/confluence/ex/confluence/{cloud_id}/wiki/api/v2/pages')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF

Base URL

https://gateway.maton.ai/confluence/{atlassian-api-path}

Confluence Cloud uses two URL patterns:

**V2 API (recommended):**

https://gateway.maton.ai/confluence/ex/confluence/{cloudId}/wiki/api/v2/{resource}

**V1 REST API (limited):**

https://gateway.maton.ai/confluence/ex/confluence/{cloudId}/wiki/rest/api/{resource}

The `{cloudId}` is required for all API calls. Obtain it via the accessible-resources endpoint (see below).

Authentication

All requests require the Maton API key in the Authorization header:

Authorization: Bearer $MATON_API_KEY

**Environment Variable:** Set your API key as `MATON_API_KEY`:

export MATON_API_KEY="YOUR_API_KEY"

Getting Your API Key

1. Sign in or create an account at [maton.ai](https://maton.ai)

2. Go to [maton.ai/settings](https://maton.ai/settings)

3. Copy your API key

Connection Management

Manage your Confluence OAuth connections at `https://ctrl.maton.ai`.

List Connections

python3 <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://ctrl.maton.ai/connections?app=confluence&status=ACTIVE')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF

Create Connection

python3 <<'EOF'
import urllib.request, os, json
data = json.dumps({'app': 'confluence'}).encode()
req = urllib.request.Request('https://ctrl.maton.ai/connections', data=data, method='POST')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
req.add_header('Content-Type', 'application/json')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF

Get Connection

python3 <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://ctrl.maton.ai/connections/{connection_id}')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF

**Response:**

{
  "connection": {
    "connection_id": "6cb7787f-7c32-4658-a3c3-4ddf1367a4ce",
    "status": "ACTIVE",
    "creation_time": "2026-02-13T00:00:00.000000Z",
    "last_updated_time": "2026-02-13T00:00:00.000000Z",
    "url": "https://connect.maton.ai/?session_token=...",
    "app": "confluence",
    "metadata": {}
  }
}

Open the returned `url` in a browser to complete OAuth authorization.

Delete Connection

python3 <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://ctrl.maton.ai/connections/{connection_id}', method='DELETE')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF

Specifying Connection

If you have multiple Confluence connections, specify which one to use with the `Maton-Connection` header:

python3 <<'EOF'
import urllib.request, os, json
cloud_id = "YOUR_CLOUD_ID"
req = urllib.request.Request(f'https://gateway.maton.ai/confluence/ex/confluence/{cloud_id}/wiki/api/v2/pages')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
req.add_header('Maton-Connection', '6cb7787f-7c32-4658-a3c3-4ddf1367a4ce')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF

If omitted, the gateway uses the default (oldest) active connection.

Getting Your Cloud ID

Before making API calls, you must obtain your Confluence Cloud ID:

python3 <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://gateway.maton.ai/confluence/oauth/token/accessible-resources')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
resources = json.load(urllib.request.urlopen(req))
print(json.dumps(resources, indent=2))
# Use resources[0]['id'] as your cloudId
EOF

**Response:**

[
  {
    "id": "62909843-b784-4c35-b770-e4e2a26f024b",
    "name": "your-site-name",
    "url": "https://your-site.atlassian.net",
    "scopes": ["read:confluence-content.all", "write:confluence-content", ...],
    "avatarUrl": "https://..."
  }
]

API Reference

All V2 API endpoints use the base path:

/confluence/ex/confluence/{cloudId}/wiki/api/v2

Pages

#### List Pages

GET /pages
GET /pages?space-id={spaceId}
GET /pages?limit=25
GET /pages?status=current
GET /pages?body-format=storage

**Response:**

{
  "results": [
    {
      "id": "98391",
      "status": "current",
      "title": "My Page",
      "spaceId": "98306",
      "parentId": "98305",
      "parentType": "page",
      "authorId": "557058:...",
      "createdAt": "2026-02-12T23:00:00.000Z",
      "version": {
        "number": 1,
        "authorId": "557058:...",
        "createdAt": "2026-02-12T23:00:00.000Z"
      },
      "_links": {
        "webui": "/spaces/SPACEKEY/pages/98391/My+Page"
      }
    }
  ],
  "_links": {
    "next": "/wiki/api/v2/pages?cursor=..."
  }
}

#### Get Page

GET /pages/{pageId}
GET /pages/{pageId}?body-format=storage
GET /pages/{pageId}?body-format=atlas_doc_format
GET /pages/{pageId}?body-format=view

**Body formats:**

  • `storage` - Confluence storage format (XML-like)
  • `atlas_doc_format` - Atlassian Document Format (JSON)
  • `view` - Rendered HTML
  • #### Create Page

    POST /pages
    Content-Type: application/json
    
    {
      "spaceId": "98306",
      "status": "current",
      "title": "New Page Title",
      "body": {
        "representation": "storage",
        "value": "<p>Page content in storage format</p>"
      }
    }

    To create a child page, include `parentId`:

    {
      "spaceId": "98306",
      "parentId": "98391",
      "status": "current",
      "title": "Child Page",
      "body": {
        "representation": "storage",
        "value": "<p>Child page content</p>"
      }
    }

    **Response:**

    {
      "id": "98642",
      "status": "current",
      "title": "New Page Title",
      "spaceId": "98306",
      "version": {
        "number": 1
      }
    }

    #### Update Page

    PUT /pages/{pageId}
    Content-Type: application/json
    
    {
      "id": "98391",
      "status": "current",
      "title": "Updated Page Title",
      "body": {
        "representation": "storage",
        "value": "<p>Updated content</p>"
      },
      "version": {
        "number": 2,
        "message": "Updated via API"
      }
    }

    **Note:** You must increment the version number with each update.

    #### Delete Page

    DELETE /pages/{pageId}

    Returns `204 No Content` on success.

    #### Get Page Children

    GET /pages/{pageId}/children

    #### Get Page Versions

    GET /pages/{pageId}/versions

    #### Get Page Labels

    GET /pages/{pageId}/labels

    #### Get Page Attachments

    GET /pages/{pageId}/attachments

    #### Get Page Comments

    GET /pages/{pageId}/footer-comments

    #### Get Page Properties

    GET /pages/{pageId}/properties
    GET /pages/{pageId}/properties/{propertyId}

    #### Create Page Property

    POST /pages/{pageId}/properties
    Content-Type: application/json
    
    {
      "key": "my-property-key",
      "value": {"customKey": "customValue"}
    }

    #### Update Page Property

    PUT /pages/{pageId}/properties/{propertyId}
    Content-Type: application/json
    
    {
      "key": "my-property-key",
      "value": {"customKey": "updatedValue"},
      "version": {"number": 2}
    }

    #### Delete Page Property

    DELETE /pages/{pageId}/properties/{propertyId}

    Spaces

    #### List Spaces

    GET /spaces
    GET /spaces?limit=25
    GET /spaces?type=global

    **Response:**

    {
      "results": [
        {
          "id": "98306",
          "key": "SPACEKEY",
          "name": "Space Name",
          "type": "global",
          "status": "current",
          "authorId": "557058:...",
          "createdAt": "2026-02-12T23:00:00.000Z",
          "homepageId": "98305",
          "_links": {
            "webui": "/spaces/SPACEKEY"
          }
        }
      ]
    }

    #### Get Space

    GET /spaces/{spaceId}

    #### Get Space Pages

    GET /spaces/{spaceId}/pages

    #### Get Space Blogposts

    GET /spaces/{spaceId}/blogposts

    #### Get Space Properties

    GET /spaces/{spaceId}/properties

    #### Create Space Property

    POST /spaces/{spaceId}/properties
    Content-Type: application/json
    
    {
      "key": "space-property-key",
      "value": {"key": "value"}
    }

    #### Get Space Permissions

    GET /spaces/{spaceId}/permissions

    #### Get Space Labels

    GET /spaces/{spaceId}/labels

    Blogposts

    #### List Blogposts

    GET /blogposts
    GET /blogposts?space-id={spaceId}
    GET /blogposts?limit=25

    #### Get Blogpost

    GET /blogposts/{blogpostId}
    GET /blogposts/{blogpostId}?body-format=storage

    #### Create Blogpost

    POST /blogposts
    Content-Type: application/json
    
    {
      "spaceId": "98306",
      "title": "My Blog Post",
      "body": {
        "representation": "storage",
        "value": "<p>Blog post content</p>"
      }
    }

    #### Update Blogpost

    PUT /blogposts/{blogpostId}
    Content-Type: application/json
    
    {
      "id": "458753",
      "status": "current",
      "title": "Updated Blog Post",
      "body": {
        "representation": "storage",
        "value": "<p>Updated content</p>"
      },
      "version": {
        "number": 2
      }
    }

    #### Delete Blogpost

    DELETE /blogposts/{blogpostId}

    #### Get Blogpost Labels

    GET /blogposts/{blogpostId}/labels

    #### Get Blogpost Versions

    GET /blogposts/{blogpostId}/versions

    #### Get Blogpost Comments

    GET /blogposts/{blogpostId}/footer-comments

    Comments

    #### List Footer Comments

    GET /footer-comments
    GET /footer-comments?body-format=storage

    #### Get Comment

    GET /footer-comments/{commentId}

    #### Create Footer Comment

    POST /footer-comments
    Content-Type: application/json
    
    {
      "pageId": "98391",
      "body": {
        "representation": "storage",
        "value": "<p>Comment text</p>"
      }
    }

    For blogpost comments:

    {
      "blogpostId": "458753",
      "body": {
        "representation": "storage",
        "value": "<p>Comment on blogpost</p>"
      }
    }

    #### Update Comment

    PUT /footer-comments/{commentId}
    Content-Type: application/json
    
    {
      "version": {"number": 2},
      "body": {
        "representation": "storage",
        "value": "<p>Updated comment</p>"
      }
    }

    #### Delete Comment

    DELETE /footer-comments/{commentId}

    #### Get Comment Replies

    GET /footer-comments/{commentId}/children

    #### List Inline Comments

    GET /inline-comments

    Attachments

    #### List Attachments

    GET /attachments
    GET /attachments?limit=25

    #### Get Attachment

    GET /attachments/{attachmentId}

    #### Get Page Attachments

    GET /pages/{pageId}/attachments

    Tasks

    #### List Tasks

    GET /tasks

    #### Get Task

    GET /tasks/{taskId}

    Labels

    #### List Labels

    GET /labels
    GET /labels?prefix=global

    Custom Content

    #### List Custom Content

    GET /custom-content
    GET /custom-content?type={customContentType}

    User (V1 API)

    The current user endpoint uses the V1 REST API:

    GET /confluence/ex/confluence/{cloudId}/wiki/rest/api/user/current

    **Response:**

    {
      "type": "known",
      "accountId": "557058:...",
      "accountType": "atlassian",
      "email": "user@example.com",
      "publicName": "User Name",
      "displayName": "User Name"
    }

    Pagination

    The V2 API uses cursor-based pagination. Responses include a `_links.next` URL when more results are available.

    GET /pages?limit=25

    **Response:**

    {
      "results": [...],
      "_links": {
        "next": "/wiki/api/v2/pages?cursor=eyJpZCI6Ijk4MzkyIn0"
      }
    }

    To get the next page, extract the cursor and pass it:

    GET /pages?limit=25&cursor=eyJpZCI6Ijk4MzkyIn0

    Code Examples

    JavaScript

    // Get Cloud ID first
    const resourcesRes = await fetch(
      'https://gateway.maton.ai/confluence/oauth/token/accessible-resources',
      {
        headers: {
          'Authorization': `Bearer ${process.env.MATON_API_KEY}`
        }
      }
    );
    const resources = await resourcesRes.json();
    const cloudId = resources[0].id;
    
    // List pages
    const response = await fetch(
      `https://gateway.maton.ai/confluence/ex/confluence/${cloudId}/wiki/api/v2/pages`,
      {
        headers: {
          'Authorization': `Bearer ${process.env.MATON_API_KEY}`
        }
      }
    );
    const data = await response.json();

    Python

    import os
    import requests
    
    # Get Cloud ID first
    resources = requests.get(
        'https://gateway.maton.ai/confluence/oauth/token/accessible-resources',
        headers={'Authorization': f'Bearer {os.environ["MATON_API_KEY"]}'}
    ).json()
    cloud_id = resources[0]['id']
    
    # List pages
    response = requests.get(
        f'https://gateway.maton.ai/confluence/ex/confluence/{cloud_id}/wiki/api/v2/pages',
        headers={'Authorization': f'Bearer {os.environ["MATON_API_KEY"]}'}
    )
    data = response.json()

    Notes

  • **Cloud ID Required**: You must obtain your Cloud ID via `/oauth/token/accessible-resources` before making API calls
  • **V2 API Recommended**: Use the V2 API (`/wiki/api/v2/`) for most operations. The V1 API (`/wiki/rest/api/`) is limited
  • **Body Formats**: Use `storage` format for creating/updating content. Use `view` for rendered HTML
  • **Version Numbers**: When updating pages or blogposts, you must increment the version number
  • **Storage Format**: Content uses Confluence storage format (XML-like). Example: `<p>Paragraph</p>`, `<h1>Heading</h1>`
  • **Delete Returns 204**: DELETE operations return 204 No Content with no response body
  • **IDs are Strings**: Page, space, and other IDs should be passed as strings
  • **IMPORTANT**: When piping curl output to `jq` or other commands, environment variables like `$MATON_API_KEY` may not expand correctly in some shell environments
  • Error Handling

    | Status | Meaning |

    |--------|---------|

    | 400 | Bad request or malformed data |

    | 401 | Invalid API key or insufficient OAuth scopes |

    | 403 | Permission denied |

    | 404 | Resource not found |

    | 409 | Conflict (e.g., duplicate title) |

    | 429 | Rate limited |

    | 4xx/5xx | Passthrough error from Confluence API |

    Troubleshooting: API Key Issues

    1. Check that the `MATON_API_KEY` environment variable is set:

    echo $MATON_API_KEY

    2. Verify the API key is valid by listing connections:

    python3 <<'EOF'
    import urllib.request, os, json
    req = urllib.request.Request('https://ctrl.maton.ai/connections')
    req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
    print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
    EOF

    Troubleshooting: Invalid App Name

    Ensure your URL path starts with `confluence`. For example:

  • Correct: `https://gateway.maton.ai/confluence/ex/confluence/{cloudId}/wiki/api/v2/pages`
  • Incorrect: `https://gateway.maton.ai/ex/confluence/{cloudId}/wiki/api/v2/pages`
  • Troubleshooting: Scope Issues

    If you receive a 401 error with "scope does not match", you may need to re-authorize with the required scopes. Delete your connection and create a new one:

    # Delete existing connection
    python3 <<'EOF'
    import urllib.request, os, json
    req = urllib.request.Request('https://ctrl.maton.ai/connections/{connection_id}', method='DELETE')
    req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
    print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
    EOF
    
    # Create new connection
    python3 <<'EOF'
    import urllib.request, os, json
    data = json.dumps({'app': 'confluence'}).encode()
    req = urllib.request.Request('https://ctrl.maton.ai/connections', data=data, method='POST')
    req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
    req.add_header('Content-Type', 'application/json')
    print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
    EOF

    Resources

  • [Confluence REST API V2 Documentation](https://developer.atlassian.com/cloud/confluence/rest/v2/intro/)
  • [Confluence REST API V2 Reference](https://developer.atlassian.com/cloud/confluence/rest/v2/api-group-page/)
  • [Confluence Storage Format](https://confluence.atlassian.com/doc/confluence-storage-format-790796544.html)
  • [Maton Community](https://discord.com/invite/dBfFAcefs2)
  • [Maton Support](mailto:support@maton.ai)
  • // Comments
    Sign in with GitHub to leave a comment.
    // Related skills

    More tools from the same signal band