Python Atlassian REST API Wrapper providing comprehensive access to Jira, Confluence, Bitbucket, and other Atlassian products
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Comprehensive Confluence REST API client providing full access to Confluence content management, collaboration features, and administration. Supports both Confluence Cloud and Server/Data Center platforms with 130+ public methods covering pages, spaces, attachments, users, and system management.
class Confluence(AtlassianRestAPI):
def __init__(self, url: str, username: str = None, password: str = None,
token: str = None, cloud: bool = None, api_version: str = "latest",
**kwargs):
"""
Initialize Confluence client.
Parameters:
- url (str): Base URL of Confluence instance
- username (str, optional): Username for authentication
- password (str, optional): Password or API token
- token (str, optional): Bearer token for authentication
- cloud (bool, optional): True for Cloud, False for Server/DC
- api_version (str): API version, defaults to "latest"
"""Core functionality for creating, reading, updating, and managing Confluence pages with comprehensive content handling.
def get_page_by_title(self, space: str, title: str, start: int = 0,
limit: int = 1, expand: Optional[str] = None,
type: str = "page") -> T_resp_json:
"""
Get page by space key and title.
Parameters:
- space: Space key
- title: Page title
- start: Starting index for pagination
- limit: Maximum results to return
- expand: Additional data to expand (body.storage, version, etc.)
- type: Content type ("page", "blogpost")
Returns:
dict: Page information with content and metadata
"""
def get_page_by_id(self, page_id: str, expand: Optional[str] = None,
status: Optional[str] = None,
version: Optional[int] = None) -> T_resp_json:
"""
Get page by ID.
Parameters:
- page_id: Page ID
- expand: Additional data to expand
- status: Page status filter
- version: Specific version number
Returns:
dict: Page data with requested expansions
"""
def create_page(self, space: str, title: str, body: str,
parent_id: Optional[str] = None, type: str = "page",
representation: str = "storage", editor: Optional[str] = None,
full_width: bool = False, status: str = "current") -> T_resp_json:
"""
Create new page.
Parameters:
- space: Space key where page will be created
- title: Page title
- body: Page content in specified representation format
- parent_id: Parent page ID for hierarchy
- type: Content type ("page", "blogpost")
- representation: Content format ("storage", "wiki", "view")
- editor: Editor type ("v1", "v2", "fabric")
- full_width: Use full page width
- status: Page status ("current", "draft")
Returns:
dict: Created page data with ID and URL
"""
def update_page(self, page_id: str, title: str, body: Optional[str] = None,
parent_id: Optional[str] = None, type: str = "page",
representation: str = "storage", minor_edit: bool = False,
version_comment: Optional[str] = None,
always_update: bool = False, full_width: bool = False) -> T_resp_json:
"""
Update existing page.
Parameters:
- page_id: Page ID to update
- title: New page title
- body: New page content (optional if only updating title)
- parent_id: New parent page ID
- type: Content type
- representation: Content format
- minor_edit: Mark as minor edit
- version_comment: Version comment for history
- always_update: Update even if no changes detected
- full_width: Use full page width
Returns:
dict: Updated page data
"""
def update_or_create(self, parent_id: str, title: str, body: str,
representation: str = "storage", minor_edit: bool = False,
version_comment: Optional[str] = None,
editor: Optional[str] = None,
full_width: bool = False) -> T_resp_json:
"""
Update page if exists, create if not.
Parameters:
- parent_id: Parent page ID
- title: Page title
- body: Page content
- representation: Content format
- minor_edit: Mark as minor edit if updating
- version_comment: Version comment
- editor: Editor type
- full_width: Use full page width
Returns:
dict: Page data (created or updated)
"""
def page_exists(self, space: str, title: str, type: Optional[str] = None) -> bool:
"""
Check if page exists.
Parameters:
- space: Space key
- title: Page title
- type: Content type filter
Returns:
bool: True if page exists
"""
def remove_page(self, page_id: str, status: Optional[str] = None,
recursive: bool = False) -> bool:
"""
Remove page.
Parameters:
- page_id: Page ID to remove
- status: Target status ("trashed" or permanent deletion)
- recursive: Remove child pages as well
Returns:
bool: True if removal successful
"""def get_child_pages(self, page_id: str) -> List[dict]:
"""
Get child pages.
Parameters:
- page_id: Parent page ID
Returns:
List[dict]: Child page list
"""
def get_page_ancestors(self, page_id: str) -> List[dict]:
"""
Get page ancestors.
Parameters:
- page_id: Page ID
Returns:
List[dict]: Ancestor pages from root to parent
"""
def get_parent_content_id(self, page_id: str) -> Optional[str]:
"""
Get parent page ID.
Parameters:
- page_id: Child page ID
Returns:
str: Parent page ID or None if no parent
"""
def get_subtree_of_content_ids(self, page_id: str) -> List[str]:
"""
Get complete subtree of page IDs.
Parameters:
- page_id: Root page ID
Returns:
List[str]: All descendant page IDs
"""def get_all_pages_from_space(self, space: str, start: int = 0, limit: int = 50,
status: Optional[str] = None,
expand: Optional[str] = None,
content_type: str = "page") -> T_resp_json:
"""
Get all pages from space.
Parameters:
- space: Space key
- start: Starting index for pagination
- limit: Maximum results per page
- status: Status filter ("current", "draft", "trashed")
- expand: Additional data to expand
- content_type: Content type filter
Returns:
dict: Pages data with pagination info
"""
def get_all_pages_by_label(self, label: str, start: int = 0, limit: int = 50,
expand: Optional[str] = None) -> T_resp_json:
"""
Get pages by label.
Parameters:
- label: Label to search for
- start: Starting index
- limit: Maximum results
- expand: Additional data to expand
Returns:
dict: Labeled pages with pagination
"""
def append_page(self, page_id: str, title: str, append_body: str,
parent_id: Optional[str] = None, type: str = "page",
representation: str = "storage",
minor_edit: bool = False) -> T_resp_json:
"""
Append content to page.
Parameters:
- page_id: Page ID to append to
- title: Page title (required for API)
- append_body: Content to append
- parent_id: Parent page ID
- type: Content type
- representation: Content format
- minor_edit: Mark as minor edit
Returns:
dict: Updated page data
"""
def is_page_content_is_already_updated(self, page_id: str, body: str,
title: Optional[str] = None) -> bool:
"""
Check if page content differs from provided content.
Parameters:
- page_id: Page ID to check
- body: Content to compare against
- title: Title to compare (optional)
Returns:
bool: True if content is already the same
"""def get_all_spaces(self, start: int = 0, limit: int = 50,
expand: Optional[str] = None, space_type: Optional[str] = None,
space_status: Optional[str] = None) -> T_resp_json:
"""
Get all spaces.
Parameters:
- start: Starting index for pagination
- limit: Maximum results per page
- expand: Additional data to expand
- space_type: Space type filter ("global", "personal")
- space_status: Status filter ("current", "archived")
Returns:
dict: Spaces list with pagination
"""
def get_space(self, space_key: str,
expand: str = "description.plain,homepage",
params: Optional[dict] = None) -> T_resp_json:
"""
Get space details.
Parameters:
- space_key: Space key
- expand: Additional data to expand
- params: Additional query parameters
Returns:
dict: Space information with metadata
"""
def create_space(self, space_key: str, space_name: str) -> T_resp_json:
"""
Create new space.
Parameters:
- space_key: Unique space key
- space_name: Space display name
Returns:
dict: Created space data
"""
def delete_space(self, space_key: str) -> bool:
"""
Delete space.
Parameters:
- space_key: Space key to delete
Returns:
bool: True if deletion successful
"""
def get_home_page_of_space(self, space_key: str) -> T_resp_json:
"""
Get space homepage.
Parameters:
- space_key: Space key
Returns:
dict: Homepage data
"""def attach_file(self, filename: str, name: Optional[str] = None,
content_type: Optional[str] = None, page_id: Optional[str] = None,
title: Optional[str] = None, space: Optional[str] = None,
comment: Optional[str] = None) -> T_resp_json:
"""
Attach file to page.
Parameters:
- filename: Path to file to attach
- name: Attachment name (defaults to filename)
- content_type: MIME type
- page_id: Target page ID
- title: Target page title (used with space if no page_id)
- space: Target space key (used with title if no page_id)
- comment: Attachment comment
Returns:
dict: Attachment metadata
"""
def attach_content(self, content: bytes, name: str,
content_type: str = "application/binary",
page_id: Optional[str] = None, title: Optional[str] = None,
space: Optional[str] = None,
comment: Optional[str] = None) -> T_resp_json:
"""
Attach content from memory to page.
Parameters:
- content: Binary content to attach
- name: Attachment name
- content_type: MIME type
- page_id: Target page ID
- title: Target page title
- space: Target space key
- comment: Attachment comment
Returns:
dict: Attachment metadata
"""
def get_attachments_from_content(self, page_id: str, start: int = 0,
limit: int = 50, expand: Optional[str] = None,
filename: Optional[str] = None,
media_type: Optional[str] = None) -> T_resp_json:
"""
Get page attachments.
Parameters:
- page_id: Page ID
- start: Starting index
- limit: Maximum results
- expand: Additional data to expand
- filename: Filter by filename
- media_type: Filter by media type
Returns:
dict: Attachments list with metadata
"""
def download_attachments_from_page(self, page_id: str, path: Optional[str] = None,
start: int = 0, limit: int = 50,
filename: Optional[str] = None,
to_memory: bool = False) -> Union[None, List[bytes]]:
"""
Download attachments from page.
Parameters:
- page_id: Page ID
- path: Download directory path
- start: Starting index
- limit: Maximum attachments to download
- filename: Specific filename to download
- to_memory: Return content in memory instead of saving files
Returns:
None or List[bytes]: Downloaded content if to_memory=True
"""
def delete_attachment(self, page_id: str, filename: str,
version: Optional[int] = None) -> bool:
"""
Delete attachment.
Parameters:
- page_id: Page ID
- filename: Attachment filename
- version: Specific version to delete
Returns:
bool: True if deletion successful
"""def add_comment(self, page_id: str, text: str) -> T_resp_json:
"""
Add comment to page.
Parameters:
- page_id: Page ID
- text: Comment text (supports wiki markup)
Returns:
dict: Created comment data
"""
def get_page_comments(self, content_id: str, expand: Optional[str] = None,
parent_version: Optional[int] = None, start: int = 0,
limit: int = 25, location: Optional[str] = None,
depth: Optional[str] = None) -> T_resp_json:
"""
Get page comments.
Parameters:
- content_id: Page ID
- expand: Additional data to expand
- parent_version: Parent version filter
- start: Starting index
- limit: Maximum results
- location: Comment location filter
- depth: Comment depth ("root", "all")
Returns:
dict: Comments data with threading
"""
def share_with_others(self, page_id: str, group: str, message: str) -> bool:
"""
Share page with group and send notification.
Parameters:
- page_id: Page ID to share
- group: Group name to notify
- message: Notification message
Returns:
bool: True if sharing successful
"""def get_page_labels(self, page_id: str, prefix: Optional[str] = None,
start: Optional[int] = None,
limit: Optional[int] = None) -> T_resp_json:
"""
Get page labels.
Parameters:
- page_id: Page ID
- prefix: Label prefix filter
- start: Starting index
- limit: Maximum results
Returns:
dict: Labels data
"""
def set_page_label(self, page_id: str, label: str) -> T_resp_json:
"""
Add label to page.
Parameters:
- page_id: Page ID
- label: Label to add
Returns:
dict: Label operation result
"""
def remove_page_label(self, page_id: str, label: str) -> T_resp_json:
"""
Remove label from page.
Parameters:
- page_id: Page ID
- label: Label to remove
Returns:
dict: Label operation result
"""
def get_page_properties(self, page_id: str) -> T_resp_json:
"""
Get all page properties.
Parameters:
- page_id: Page ID
Returns:
dict: Page properties
"""
def set_page_property(self, page_id: str, data: dict) -> T_resp_json:
"""
Set page property.
Parameters:
- page_id: Page ID
- data: Property data with key and value
Returns:
dict: Property operation result
"""
def get_page_property(self, page_id: str, page_property_key: str) -> T_resp_json:
"""
Get specific page property.
Parameters:
- page_id: Page ID
- page_property_key: Property key
Returns:
dict: Property value
"""def cql(self, cql: str, start: int = 0, limit: Optional[int] = None,
expand: Optional[str] = None,
include_archived_spaces: Optional[bool] = None,
excerpt: Optional[str] = None) -> T_resp_json:
"""
Confluence Query Language search.
Parameters:
- cql: CQL query string
- start: Starting index for pagination
- limit: Maximum results to return
- expand: Additional data to expand
- include_archived_spaces: Include archived spaces in results
- excerpt: Excerpt strategy ("highlight", "indexed", "none")
Returns:
dict: Search results with content matches
"""def get_user_details_by_username(self, username: str,
expand: Optional[str] = None) -> T_resp_json:
"""
Get user details by username.
Parameters:
- username: Username to lookup
- expand: Additional data to expand
Returns:
dict: User information
"""
def get_user_details_by_accountid(self, accountid: str,
expand: Optional[str] = None) -> T_resp_json:
"""
Get user details by account ID (Cloud).
Parameters:
- accountid: Account ID to lookup
- expand: Additional data to expand
Returns:
dict: User information
"""
def get_all_groups(self, start: int = 0, limit: int = 1000) -> T_resp_json:
"""
Get all groups.
Parameters:
- start: Starting index
- limit: Maximum results
Returns:
dict: Groups list
"""
def create_group(self, name: str) -> T_resp_json:
"""
Create group.
Parameters:
- name: Group name
Returns:
dict: Created group data
"""
def get_group_members(self, group_name: str = "confluence-users",
start: int = 0, limit: int = 1000,
expand: Optional[str] = None) -> T_resp_json:
"""
Get group members.
Parameters:
- group_name: Group name
- start: Starting index
- limit: Maximum results
- expand: Additional data to expand
Returns:
dict: Group members list
"""
def add_user_to_group(self, username: str, group_name: str) -> T_resp_json:
"""
Add user to group.
Parameters:
- username: Username to add
- group_name: Target group name
Returns:
dict: Operation result
"""def create_or_update_template(self, name: str, body: str,
template_type: str = "page",
template_id: Optional[str] = None,
description: Optional[str] = None,
labels: Optional[List[str]] = None,
space: Optional[str] = None) -> T_resp_json:
"""
Create or update content template.
Parameters:
- name: Template name
- body: Template body content
- template_type: Template type ("page", "blogpost")
- template_id: Template ID for updates
- description: Template description
- labels: Template labels
- space: Space key for space templates
Returns:
dict: Template data
"""
def get_content_templates(self, space: Optional[str] = None, start: int = 0,
limit: Optional[int] = None,
expand: Optional[str] = None) -> T_resp_json:
"""
Get content templates.
Parameters:
- space: Space key filter
- start: Starting index
- limit: Maximum results
- expand: Additional data to expand
Returns:
dict: Templates list
"""
def remove_template(self, template_id: str) -> bool:
"""
Delete template.
Parameters:
- template_id: Template ID to delete
Returns:
bool: True if deletion successful
"""def get_page_as_pdf(self, page_id: str) -> bytes:
"""
Export page as PDF.
Parameters:
- page_id: Page ID to export
Returns:
bytes: PDF content
"""
def get_page_as_word(self, page_id: str) -> bytes:
"""
Export page as Word document.
Parameters:
- page_id: Page ID to export
Returns:
bytes: Word document content
"""
def convert_wiki_to_storage(self, wiki: str) -> T_resp_json:
"""
Convert wiki markup to storage format.
Parameters:
- wiki: Wiki markup content
Returns:
dict: Storage format content
"""
def convert_storage_to_view(self, storage: str) -> T_resp_json:
"""
Convert storage format to view format.
Parameters:
- storage: Storage format content
Returns:
dict: View format content
"""def history(self, page_id: str) -> T_resp_json:
"""
Get page history.
Parameters:
- page_id: Page ID
Returns:
dict: Version history with authors and timestamps
"""
def get_content_history_by_version_number(self, content_id: str,
version_number: int) -> T_resp_json:
"""
Get specific version of content.
Parameters:
- content_id: Content ID
- version_number: Version number
Returns:
dict: Historical version data
"""
def remove_content_history(self, page_id: str, version_number: int) -> bool:
"""
Remove specific version from history.
Parameters:
- page_id: Page ID
- version_number: Version to remove
Returns:
bool: True if removal successful
"""from atlassian import Confluence
confluence = Confluence(
url="https://your-domain.atlassian.net",
username="email@example.com",
password="api-token"
)
# Create page
page_body = """
<p>This is a new page with <strong>formatted content</strong>.</p>
<ac:structured-macro ac:name="info">
<ac:parameter ac:name="title">Note</ac:parameter>
<ac:rich-text-body>
<p>This is an info macro.</p>
</ac:rich-text-body>
</ac:structured-macro>
"""
new_page = confluence.create_page(
space="DOCS",
title="My New Page",
body=page_body,
parent_id="123456"
)
# Get page
page = confluence.get_page_by_title(
"DOCS",
"My New Page",
expand="body.storage,version,ancestors"
)
# Update page
confluence.update_page(
page_id=page["id"],
title="Updated Page Title",
body="<p>Updated content</p>"
)# Get all pages from space
pages = confluence.get_all_pages_from_space(
"DOCS",
expand="body.storage,version",
limit=100
)
# Search with CQL
search_results = confluence.cql(
'space = "DOCS" AND title ~ "API" AND type = "page"',
expand="body.view"
)
# Work with labels
confluence.set_page_label(page_id, "api-docs")
confluence.set_page_label(page_id, "reference")
labels = confluence.get_page_labels(page_id)# Attach file
attachment = confluence.attach_file(
filename="/path/to/document.pdf",
page_id=page_id,
comment="Updated API documentation"
)
# Get attachments
attachments = confluence.get_attachments_from_content(page_id)
# Download attachments
confluence.download_attachments_from_page(
page_id,
path="/download/directory"
)# Create space
space = confluence.create_space(
space_key="NEWDOCS",
space_name="New Documentation Space"
)
# Get space info
space_info = confluence.get_space(
"DOCS",
expand="description.plain,homepage,permissions"
)
# User operations
user = confluence.get_user_details_by_username("john.doe")
groups = confluence.get_all_groups()
members = confluence.get_group_members("confluence-administrators")# Content conversion
wiki_content = "h1. My Heading\n\nThis is *bold* text."
storage_content = confluence.convert_wiki_to_storage(wiki_content)
# Templates
template = confluence.create_or_update_template(
name="Meeting Notes Template",
body="<h1>Meeting Notes</h1><p>Date: </p><p>Attendees: </p>",
description="Standard template for meeting notes"
)
# Export operations
pdf_content = confluence.get_page_as_pdf(page_id)
with open("page.pdf", "wb") as f:
f.write(pdf_content)
# Page hierarchy
children = confluence.get_child_pages(parent_page_id)
ancestors = confluence.get_page_ancestors(page_id)from atlassian.errors import ApiNotFoundError, ApiPermissionError
try:
page = confluence.get_page_by_title("INVALID", "Nonexistent Page")
except ApiNotFoundError:
print("Page not found")
except ApiPermissionError:
print("Permission denied")from atlassian.typehints import T_id, T_resp_json
from typing import List, Dict, Optional, Union
# Common parameter types
SpaceKey = str
PageTitle = str
ContentId = str
ContentRepresentation = str # "storage", "wiki", "view"
ContentStatus = str # "current", "draft", "trashed"
CQLQuery = strInstall with Tessl CLI
npx tessl i tessl/pypi-atlassian-python-api