Confluence module¶
Complete API reference¶
The task-oriented sections below explain the most common workflows. These source-backed references list every public method and current signature for Server/Data Center, legacy Cloud, and the explicit Cloud V2 client.
The Confluence module now provides both Cloud and Server implementations with dedicated APIs for each platform.
New Implementation¶
The new Confluence implementation follows the same pattern as other modules with dedicated Cloud and Server classes:
from atlassian.confluence import ConfluenceCloud, ConfluenceServer
# For Confluence Cloud
confluence_cloud = ConfluenceCloud(
url="https://your-domain.atlassian.net",
username="you@example.com",
password="your-cloud-api-token",
)
# Cloud API tokens use HTTP Basic auth. Do not pass them as ``token=``:
# that creates a Bearer header for Server/Data Center personal access tokens.
# The client constructs the Basic header; do not base64-encode credentials.
with open("CONFLUENCE_TOKEN", encoding="utf-8") as token_file:
api_token = token_file.read().strip()
confluence_cloud = ConfluenceCloud(
url="https://your-domain.atlassian.net",
username="you@example.com",
password=api_token,
)
# For Confluence Server
confluence_server = ConfluenceServer(
url="https://your-confluence-server.com",
username="your-username",
password="your-password"
)
Cloud vs Server Differences¶
Choosing a Cloud client¶
ConfluenceCloud is the established Cloud client and keeps compatibility
methods for older Cloud REST endpoints. Use ConfluenceV2 for the versioned
Cloud V2 interface and new V2-only resources such as whiteboards, folders,
databases, data classification, and V2 content properties. Both use the Cloud
/wiki/api/v2 root for V2 operations; legacy operations retain their
documented /wiki/rest/api paths.
from atlassian import ConfluenceV2
confluence = ConfluenceV2(
"https://your-domain.atlassian.net",
username="you@example.com",
password="your-api-token",
)
For scoped Cloud API tokens through https://api.atlassian.com/ex/confluence/<cloud-id>,
use ConfluenceV2. This preserves the gateway URL and targets the V2
endpoints supported by scoped tokens.
Space endpoint versions¶
The endpoint is selected by API version, not by the method name:
Server/Data Center REST V1 uses
/rest/api/space(or/wiki/rest/api/spacewhen the instance uses the/wikicontext).Cloud REST V2 uses
/wiki/api/v2/spaces.
For Server/Data Center (and legacy Cloud V1 installations), filter by one
space category label with get_all_spaces(label="service"). Cloud V2 uses
the plural list filter: get_spaces(labels=["service"]).
The Cloud V1 Postman collection does not define a public Get spaces
operation; use Cloud V2 for space enumeration. ConfluenceV2 and
ConfluenceCloud use the V2 plural endpoint. Their
get_spaces(ids=[...], keys=[...], labels=[...]) filters are encoded as
repeated V2 query parameters. ConfluenceCloud.get_spaces() returns one V2
response page and get_all_spaces() lazily follows its cursor pages;
ConfluenceV2.get_spaces() returns the fully paginated list.
Set a space homepage (Server/Data Center)¶
Set an existing page as a space homepage with set_space_homepage. The
calling user needs space-administration permission and access to the page.
confluence.set_space_homepage("TEAM", "123456789")
For other space metadata, use update_space(space_key, data) with the
corresponding Confluence REST space payload.
Common Operations¶
Both implementations support:
Content management (create, read, update, delete)
Space management
User and group management
Label management
Attachment handling
Comment management
Search functionality
Page properties
Export capabilities
Server-Specific Features¶
The Server implementation includes additional features:
Draft content management
Trash content management
Reindex operations
Space permissions
Space settings
Legacy Implementation¶
The original Confluence implementation is still available for backward compatibility.
Get page info¶
# Check page exists
# type of the page, 'page' or 'blogpost'. Defaults to 'page'
# Cloud uses V2 space/page lookups; Server/Data Center keeps its REST API.
confluence.page_exists(space, title, type=None)
# Resolve direct, display, and shared short page URLs to a page ID.
page_id = confluence.get_page_id_by_url("https://confluence.example.com/x/-_Z3")
# For Server/Data Center, use this paginated helper for all group members.
members = confluence.get_all_members("confluence-users")
# Returns only space names and follows the space-directory pagination.
space_names = confluence.get_space_names()
# Provide content by type (page, blog, comment)
confluence.get_page_child_by_type(page_id, type='page', start=None, limit=None, expand=None)
# Get child information without listing or paginating every child.
child_count = confluence.get_page_child_count(page_id)
has_children = confluence.page_has_children(page_id)
# Stream all CQL matches without accumulating them in memory.
for result in confluence.iter_cql('type=page', limit=250):
process(result)
# Use this only when a complete in-memory list is required.
all_results = confluence.cql_all('type=page', limit=250)
# Provide content id from search result by title and space
confluence.get_page_id(space, title)
# Provide space key from content id
confluence.get_page_space(page_id)
# Returns the list of labels on a piece of Content
confluence.get_page_by_title(space, title, start=None, limit=None)
# Get page by ID
# Example request URI(s):
# http://example.com/confluence/rest/api/content/1234?expand=space,body.view,version,container
# http://example.com/confluence/rest/api/content/1234?status=any
# page_id: Content ID
# status: (str) list of Content statuses to filter results on. Default value: [current]
# version: (int)
# expand: OPTIONAL: A comma separated list of properties to expand on the content.
# Default value: history,space,version
# We can also specify some extensions such as extensions.inlineProperties
# (for getting inline comment-specific properties) or extensions.resolution
# for the resolution status of each comment in the results
confluence.get_page_by_id(page_id, expand=None, status=None, version=None)
# The list of labels on a piece of Content
confluence.get_page_labels(page_id, prefix=None, start=None, limit=None)
# Get draft page by ID
confluence.get_draft_page_by_id(page_id, status='draft')
# Get all page by label
confluence.get_all_pages_by_label(label, start=0, limit=50, expand=None)
# Get all pages from Space
# content_type can be 'page' or 'blogpost'. Defaults to 'page'
# expand is a comma separated list of properties to expand on the content.
# max limit is 100. For more you have to loop over start values.
confluence.get_all_pages_from_space(space, start=0, limit=100, status=None, expand=None, content_type='page')
# Get all pages from space as Generator
confluence.get_all_pages_from_space_as_generator(space, start=0, limit=100, status=None, expand=None, content_type='page')
# Get list of pages from trash
confluence.get_all_pages_from_space_trash(space, start=0, limit=500, status='trashed', content_type='page')
# Get list of draft pages from space
# Use case is cleanup old drafts from Confluence
confluence.get_all_draft_pages_from_space(space, start=0, limit=500, status='draft')
# Search list of draft pages by space key
# Use case is cleanup old drafts from Confluence
confluence.get_all_draft_pages_from_space_through_cql(space, start=0, limit=500, status='draft')
# Info about all restrictions by operation
confluence.get_all_restrictions_for_content(content_id)
Page actions¶
# Create page from scratch
# Server/Data Center: ``space`` is the space KEY, not its display name.
# Personal-space keys commonly look like ``~<account-id>``.
confluence.create_page(space, title, body, parent_id=None, type='page', representation='storage', editor='v2', full_width=False)
# Check that the supplied credentials are accepted. This does not by itself
# grant create permission in a particular space.
confluence.get_current_user()
# Cloud V2 uses a space ID rather than a key. Resolve it first, then create.
from atlassian import ConfluenceV2
cloud = ConfluenceV2(url, username=email, password=api_token)
space_id = cloud.get_space_by_key('SPACEKEY')['id']
cloud.create_page(space_id=space_id, title=title, body=body)
# Server/Data Center: retain template macros and replace explicit placeholders.
confluence.create_page_from_template(
space, title, template_id, replacements={"{{REPORT_MONTH}}": "August"}
)
# With recursive=True, all descendants are listed before deletion so
# server-side pagination cannot leave later child pages behind.
confluence.remove_page(page_id, status=None, recursive=False)
# Remove any content
confluence.remove_content(content_id):
# Remove page from trash
delete_status = confluence.remove_page_from_trash(page_id) # normally 204
# Remove page as draft
confluence.remove_page_as_draft(page_id)
# Update page if already exist
confluence.update_page(page_id, title, body, parent_id=None, type='page', representation='storage', minor_edit=False, full_width=False)
# Server/Data Center updates use the configured REST API root and send a JSON body.
# Get every contributor for a collaboratively edited page revision.
contributors = confluence.get_page_version_contributors(page_id, version_number)
# Update the page only when the title exists under parent_id; a same-titled
# page elsewhere in the space is left untouched. parent_id is optional;
# use a space key to create or update a top-level page.
confluence.update_or_create(parent_id, title, body, representation='storage', full_width=False)
confluence.update_or_create(title=title, body=body, space='SPACEKEY')
# Server/Data Center: annotate the first page revision on creation.
confluence.create_page('SPACEKEY', title, body, version_comment='Initial import')
# Preserve Confluence storage macros when updating tables. Do not round-trip
# a page containing images through pandas.read_html(...).to_html(), because
# pandas represents embedded image cells as missing values and serializes
# them as ``NaN``. Fetch body.storage, update only the intended markup, and
# pass the resulting storage XHTML to update_page/update_existing_page.
# Archived pages must be restored/unarchived before update_or_create() can update them.
# Append body to page if already exist
confluence.append_page(page_id, title, append_body, parent_id=None, type='page', representation='storage', minor_edit=False)
# A list or dictionary is rendered as formatted JSON in a storage code block.
confluence.append_page(page_id, title, {"users": ["Ada", "Linus"]})
# Uploading the same attachment name creates a new attachment revision.
confluence.attach_file("images/diagram.png", page_id=page_id)
# Attachment names are filenames, not paths. Path-like values are reduced
# to their basename (for example, ``reports/diagram.png`` becomes
# ``diagram.png``).
# Attachments are files, not executable page markup. Link an HTML report
# from the page; replacing the attachment keeps this link current.
confluence.attach_file("reports/status.html", page_id=page_id)
html_attachment_link = """
<ac:link>
<ri:attachment ri:filename="status.html" />
<ac:plain-text-link-body><![CDATA[Open the HTML status report]]></ac:plain-text-link-body>
</ac:link>
"""
confluence.append_page(page_id, title, html_attachment_link)
# ``download_path=...`` remains an alias for historical examples; use
# ``path=...`` for new code.
confluence.download_attachments_from_page(page_id, path="/tmp/downloads")
# Attachments belong to the page that uploaded them. Including ``source_page``
# in another page does not copy its attachments, so query the source directly.
source_attachments = confluence.get_attachments_from_content(source_page_id)
# Server/Data Center: set all read restrictions listed below. This replaces
# the existing read restriction set, so include every allowed user/group.
confluence.set_restrictions_for_content(page_id, [{
"operation": "read",
"restrictions": {"user": [{"type": "known", "username": "alice"}]},
}])
# Confluence Cloud does not render attached HTML inline. Server/Data Center
# HTML/HTML Include macros are administrator-controlled and disabled by
# default because embedding arbitrary HTML can introduce XSS vulnerabilities.
# Fetch every historic revision without querying version numbers one by one.
# Use iter_page_versions(...) instead when processing a large history.
versions = confluence.get_all_page_versions(page_id, limit=200)
# Server/Data Center: export each page in a hierarchy. Confluence has no
# supported REST endpoint for one merged arbitrary-subtree PDF.
page_pdfs = confluence.export_page_tree_as_pdf(page_id)
for exported_page_id, pdf_bytes in confluence.iter_page_tree_as_pdf(page_id):
save_pdf(exported_page_id, pdf_bytes)
# Invalid storage XHTML raises HTTPError with Confluence's ``message``,
# ``detail``, and field-level validation errors when the server supplies them.
# Set a page property. Pass a dictionary; JSON strings are accepted for
# backwards compatibility and are converted before the request is sent.
confluence.set_page_property(page_id, {"key": "myprop", "value": {"hash": "1111"}})
# Delete the page (content) property e.g. delete key of hash
confluence.delete_page_property(page_id, page_property)
# Move page
confluence.move_page(space_key, page_id, target_title, position="append")
# Get the page (content) property e.g. get key of hash
confluence.get_page_property(page_id, page_property_key)
# Get every page (content) property. Pagination is handled automatically;
# limit controls the size of each request, not the final result size.
confluence.get_page_properties(page_id)
# Get page ancestors
confluence.get_page_ancestors(page_id)
# Attach (upload) a file to a page, if it exists it will update the
# automatically version the new file and keep the old one
# content_type is default to "application/binary"
confluence.attach_file(filename, name=None, content_type=None, page_id=None, title=None, space=None, comment=None)
# Attach (upload) a content to a page, if it exists it will update the
# automatically version the new file and keep the old one
# content_type is default to "application/binary"
confluence.attach_content(content, name=None, content_type=None, page_id=None, title=None, space=None, comment=None)
# Download attachments from a page to local system. If path is None, current working directory will be used.
# Downloads every attachment, following Confluence pagination automatically.
confluence.download_attachments_from_page(page_id, path=None)
# Remove completely a file if version is None or delete version
confluence.delete_attachment(page_id, filename, version=None)
# Remove completely a file if version is None or delete version
confluence.delete_attachment_by_id(attachment_id, version)
# Keep last versions
confluence.remove_page_attachment_keep_version(page_id, filename, keep_last_versions)
# Get attachment history
confluence.get_attachment_history(attachment_id, limit=200, start=0)
# Get attachment for content
confluence.get_attachments_from_content(page_id, start=0, limit=50, expand=None, filename=None, media_type=None)
# Check has unknown attachment error on page
confluence.has_unknown_attachment_error(page_id)
# Export page as PDF
# Use ConfluenceCloud (or Confluence(..., cloud=True)) for Cloud exports.
# ``api_version='cloud'`` is deprecated; use ConfluenceV2 for Cloud V2 APIs.
confluence.export_page(page_id)
# Server/Data Center only: legacy Word exporter. The returned bytes are a
# Word-readable multipart HTML export, not a .docx document.
word_export = confluence.get_page_as_word(page_id)
# Set a label on the page
confluence.set_page_label(page_id, label)
# Delete Confluence page label
confluence.remove_page_label(page_id, label)
# Add comment into page
confluence.add_comment(page_id, text)
# Comments are a separate paginated resource; they are not included by
# get_page_by_id(). Expand the rendered body and creator/editor metadata.
comment_page = confluence.get_page_comments(
page_id, expand='body.view,history,version', start=0, limit=100
)
for comment in comment_page['results']:
body = comment['body']['view']['value']
author = comment.get('history', {}).get('createdBy')
latest_editor = comment.get('version', {}).get('by')
# Server/Data Center only: inline annotations use an undocumented
# Confluence UI endpoint. The selection must match page text exactly.
inline_comments = confluence.get_inline_comments(page_id)
annotation = confluence.add_inline_comment(
page_id, 'selected text', '<p>Please clarify this sentence.</p>'
)
confluence.reply_to_inline_comment(page_id, annotation['id'], '<p>Done.</p>')
confluence.resolve_inline_comment(page_id, annotation['id'])
# Server/Data Center only: likes are also exposed through an undocumented
# Confluence UI endpoint. The content ID may be a page, blog post, or comment.
likes = confluence.get_likes(page_id)
confluence.add_like(page_id)
confluence.remove_like(page_id)
# Cloud V2 has separate methods for footer and inline comments. Their
# result items include authorId; request body_format for comment bodies.
footer_comments = cloud.get_page_footer_comments(page_id, body_format='view')
inline_comments = cloud.get_page_inline_comments(page_id, body_format='view')
# Fetch tables from Confluence page
confluence.get_tables_from_page(page_id)
# Get regex matches from Confluence page
confluence.scrap_regex_from_page(page_id, regex)
Reading large page bodies¶
get_page_by_id(..., expand='body.storage') returns the complete body sent
by Confluence; the client does not paginate or truncate an individual page
body. IDE debuggers and interactive-variable viewers may abbreviate large
strings, which can look like a partial API result. Check the string length or
write it to a file before concluding that content is missing.
page = confluence.get_page_by_id(page_id, expand='body.storage')
storage = page['body']['storage']['value']
print(f'Received {len(storage)} characters')
with open('page-storage.xhtml', 'w', encoding='utf-8') as output:
output.write(storage)
If the request itself times out, set a larger timeout when creating the
client. This controls the HTTP request duration; it does not change the amount
of content returned by Confluence.
confluence = Confluence(url=url, username=username, password=password, timeout=150)
Storage-format updates¶
representation='storage' expects Confluence storage XHTML, including
ac: and ri: macros already present in the page. It is not generic
browser HTML. Fetch body.storage, preserve macros, and replace only the
dynamic values you own.
from xml.sax.saxutils import escape
page = confluence.get_page_by_id(page_id, expand='body.storage')
storage = page['body']['storage']['value']
# Escape dynamic text only. Do not escape the complete document: that
# would turn <ac:...> macros into literal text.
storage = storage.replace('{{SUMMARY}}', escape('Revenue & growth'))
confluence.update_page(page_id, page['title'], storage, representation='storage')
A literal & must be &. Existing entities such as " are
already valid storage XML and must not be escaped a second time. Parentheses do
not require XML escaping. representation='wiki' is legacy wiki markup;
prefer storage XHTML for pages users will edit in the browser.
JSON in a code-block macro¶
Confluence code blocks are storage-format macros. Serialize structured output
with the standard library, place it in an ac:plain-text-body CDATA section,
and set the code language to json. This preserves indentation and enables
JSON syntax highlighting in the Confluence editor.
import json
def confluence_json_code_block(server_output):
json_text = json.dumps(server_output, indent=2, sort_keys=True, ensure_ascii=False)
# CDATA cannot contain ``]]>``. Split that sequence so arbitrary JSON
# string values remain valid Confluence storage XML.
json_text = json_text.replace("]]>", "]]]]><![CDATA[>")
return (
'<ac:structured-macro ac:name="code" ac:schema-version="1">'
'<ac:parameter ac:name="language">json</ac:parameter>'
f'<ac:plain-text-body><![CDATA[{json_text}]]></ac:plain-text-body>'
'</ac:structured-macro>'
)
page = confluence.get_page_by_id(page_id, expand='body.storage')
body = page['body']['storage']['value']
body = body.replace('{{SERVER_OUTPUT}}', confluence_json_code_block(server_output))
confluence.update_page(page_id, page['title'], body, representation='storage')
The placeholder must be part of an existing storage-format page template. Do
not use html.escape on the returned macro: doing so would display the macro
as literal text instead of rendering a code block.
Word document imports¶
Confluence Server/Data Center’s Import Word document action is provided by
the Office Connector user interface. It is not exposed as a supported REST API,
and Confluence Cloud’s REST APIs likewise do not accept a .doc or .docx
file as a page body. Consequently, this package intentionally has no
import_word_document() method: using an internal browser endpoint would be
fragile and could lose document content.
For a faithful, one-off import (including the UI options to replace a page or split a document by headings), use the Confluence web interface. For automated workflows, convert the document with a tool chosen and controlled by your application, validate the resulting storage XHTML, and then use the normal page methods. Conversion of Word styles, images, tables, and macros is outside the scope of the REST API and must be validated for the documents you support.
# ``storage_xhtml`` is produced and validated by your own DOCX conversion
# step. It is Confluence storage XHTML, not the original DOCX bytes.
page = confluence.create_page(space_key, title, storage_xhtml,
representation='storage')
# Optionally retain the original source document as an attachment. This
# uploads the file; it does not convert it into page content.
confluence.attach_file('report.docx', page_id=page['id'])
Confluence Whiteboards¶
Whiteboards are available through Confluence Cloud REST API V2 only. Use
ConfluenceV2 (or ConfluenceCloud) and a token with the relevant
read:whiteboard:confluence, write:whiteboard:confluence, and
delete:whiteboard:confluence scopes.
from atlassian import ConfluenceV2
confluence = ConfluenceV2(url, username=email, password=api_token)
# Create a whiteboard in a space. ``private`` is an optional API query
# parameter; parent_id, template_key, and locale are optional body fields.
whiteboard = confluence.create_whiteboard(
space_id, title='Planning', parent_id=page_id, private=True
)
# Fetch it, optionally expanding related information.
whiteboard = confluence.get_whiteboard(
whiteboard['id'], include_collaborators=True,
include_direct_children=True, include_operations=True,
include_properties=True,
)
# Deletion moves the whiteboard to trash, where Confluence can restore it.
confluence.delete_whiteboard(whiteboard['id'])
get_whiteboard_by_id() remains as a compatible alias for
get_whiteboard(). Whiteboards are not supported by Confluence Server or
Data Center.
Confluence Cloud GraphQL search¶
ConfluenceV2 also supports the Atlassian GraphQL Gateway for Cloud-only
use cases such as advanced search. GraphQL has a continuously evolving schema,
so REST/CQL search() remains unchanged and GraphQL responses are returned
without translation. Use a tenanted *.atlassian.net URL with an API token;
the GraphQL gateway is not available on Confluence Server or Data Center.
from atlassian import ConfluenceV2
confluence = ConfluenceV2(url, username=email, password=api_token)
# Find this once from https://your-site.atlassian.net/_edge/tenant_info.
cloud_id = "your-confluence-cloud-id"
response = confluence.search_graphql("deployment guide", cloud_id)
# GraphQL may return HTTP 200 with an errors field, so inspect it first.
if response.get("errors"):
raise RuntimeError(response["errors"])
search = response["data"]["search"]["search"]
for edge in search["edges"]:
print(edge["node"]["title"], edge["node"]["url"])
For custom queries or mutations, call confluence.graphql(query, variables).
The GraphQL Gateway has its own query-cost rate limit, separate from REST API
limits.
Confluence Cloud V2 content properties¶
Cloud V2 property endpoints share the same lifecycle across pages, blog posts,
attachments, comments, custom content, folders, whiteboards, databases, and
embeds. content_type selects the documented V2 resource name; pagination is
handled automatically when listing properties.
properties = confluence.get_v2_content_properties("page", page_id)
created = confluence.create_v2_content_property(
"page", page_id, {"key": "report", "value": {"published": True}}
)
property_data = confluence.get_v2_content_property("page", page_id, created["id"])
confluence.update_v2_content_property("page", page_id, created["id"], property_data)
confluence.delete_v2_content_property("page", page_id, created["id"])
The *_v2 names distinguish these helpers from the legacy V1 key-based
content-property API. Supported content types are attachment, blogpost,
comment, custom_content, database, embed, folder, page,
and whiteboard.
Confluence Cloud V2 data classification¶
Data classification is available only to eligible Confluence Cloud sites. The site administrator defines the available levels; the caller needs the relevant content or space permissions.
levels = confluence.get_classification_levels()
confluence.update_content_classification_level("page", page_id, levels[0]["id"])
current_level = confluence.get_content_classification_level("page", page_id)
# Make a level the default for a space, or reset a page to that default.
confluence.update_space_default_classification_level(space_id, levels[0]["id"])
confluence.reset_content_classification_level("page", page_id)
Supported content types are page, blogpost, whiteboard, and
database. Content-level updates accept only the current and draft
statuses required by the V2 API.
Confluence Cloud tasks¶
from atlassian import ConfluenceV2
confluence = ConfluenceV2(url, username=email, password=api_token)
# Retrieves every result page. Filters accept account IDs, content IDs,
# and Unix epoch milliseconds for the date-range arguments.
tasks = confluence.get_tasks(status="incomplete", page_ids=[page_id])
task = confluence.get_task(task_id, body_format="storage")
confluence.update_task(task_id, "complete")
# Scoped tokens require read:task:confluence or write:task:confluence.
Template actions¶
The methods below use Confluence’s supported template endpoints. They apply to
Server/Data Center and to the legacy Cloud V1 template API; they are not part
of ConfluenceV2.
Migration from experimental template methods¶
The older experimental methods remain available for compatibility but emit a
DeprecationWarning. Use their supported replacements in new code:
get_template_by_id(template_id)->get_content_template(template_id)get_all_templates_from_space(space)->get_content_templates(space)get_all_blueprints_from_space(space)->get_blueprint_templates(space)
# Read a content template. Requesting this supported method rather than
# get_template_by_id() avoids the experimental endpoint.
template = confluence.get_content_template(template_id)
storage_body = template['body']['storage']
# Create a space template. Omit space to create a global template.
created = confluence.create_or_update_template(
name='Monthly report',
body={'storage': {'value': '<p>{{SUMMARY}}</p>', 'representation': 'storage'}},
description='Starting point for monthly reports',
labels=[{'prefix': 'global', 'name': 'report'}],
space='TEAM',
)
# Update an existing template. Use keyword arguments so template_id is
# never confused with template_type or description.
updated = confluence.create_or_update_template(
name=template['name'],
body={'storage': storage_body},
template_id=template_id,
description=template.get('description'),
)
# Get all global content templates
confluence.get_content_templates()
# Get content templates in a space
confluence.get_content_templates(space)
# Get all global blueprint templates
confluence.get_blueprint_templates()
# Get all blueprint templates in a space
confluence.get_blueprint_templates(space)
# Removing a template
confluence.remove_template(template_id)
create_or_update_template supports content templates only. Confluence does
not allow blueprint templates to be created or updated through this REST API.
Use get_blueprint_templates to inspect blueprint templates; removing a
modified blueprint resets it to its inherited/default version.
Get spaces info¶
# Get all spaces with provided limit
# additional info, e.g. metadata, icon, description, homepage
confluence.get_all_spaces(start=0, limit=500, expand=None)
# Get information about a space through space key
confluence.get_space(space_key, expand='description.plain,homepage')
# Get space content (configuring by the expand property)
confluence.get_space_content(space_key, depth="all", start=0, limit=500, content_type=None, expand="body.storage")
# Get Space permissions set based on json-rpc call
confluence.get_space_permissions(space_key)
# Experimental UI export: returns a temporary download URL for HTML, CSV,
# or XML. This is not a supported REST API and can change.
download_url = confluence.get_space_export(space_key, export_type='html')
# Export several spaces sequentially. Do not parallelize UI exports: the
# Confluence export service limits concurrent jobs.
for space_key, download_url in confluence.iter_space_exports(
["ENG", "HR", "SUPPORT"], export_type="html"
):
print(space_key, download_url)
get_space_export and iter_space_exports use Confluence’s browser
export workflow because there is no supported REST endpoint for this task.
Confluence can reject concurrent export jobs, so process spaces sequentially
and download each returned temporary URL before it expires. For Data Center
PDF exports, an administrator can tune the server-side concurrency limit; the
client cannot safely override it.
Space¶
# Archive the given Space identified by spaceKey.
# This method is idempotent i.e.,
# if the Space is already archived then no action will be taken.
confluence.archive_space(space_key)
# Get trash contents of space
confluence.get_trashed_contents_by_space(space_key, cursor=None, expand=None, limit=100)
# Remove all trash contents of space
confluence.remove_trashed_contents_by_space(space_key)
Get space permissions¶
# Returns list of permissions granted to users and groups in the particular space.
confluence.get_all_space_permissions(space_key)
# Sets permissions to multiple users/groups in the given space.
confluence.set_permissions_to_multiple_items_for_space(self, space_key, user_key=None, group_name=None, operations=None)
# Get permissions granted to anonymous user for the given space
confluence.get_permissions_granted_to_anonymous_for_space(space_key)
# Grant permissions to anonymous user in the given space.
# Operation doesn't override existing permissions
# will only add those one that weren't granted before.
# Multiple permissions could be passed in one request.
# Supported targetType and operationKey pairs:
# space read
# space administer
# space export
# space restrict
# space delete_own
# space delete_mail
# page create
# page delete
# blogpost create
# blogpost delete
# comment create
# comment delete
# attachment create
# attachment delete
confluence.set_permissions_to_anonymous_for_space(space_key, operations=None)
# Remove permissions granted to anonymous user for the given space
confluence.remove_permissions_granted_to_anonymous_for_space(space_key)
# Get permissions granted to group for the given space
confluence.get_permissions_granted_to_group_for_space(space_key, user_key)
# Grant permissions to group in the given space.
# Operation doesn't override existing permissions
# will only add those one that weren't granted before.
# Multiple permissions could be passed in one request.
# Supported targetType and operationKey pairs:
# space read
# space administer
# space export
# space restrict
# space delete_own
# space delete_mail
# page create
# page delete
# blogpost create
# blogpost delete
# comment create
# comment delete
# attachment create
# attachment delete
confluence.set_permissions_to_group_for_space(space_key, user_key, operations=None)
# Remove permissions granted to group for the given space
confluence.remove_permissions_from_group_for_space(space_key, group_name)
# Get permissions granted to user for the given space
confluence.get_permissions_granted_to_user_for_space(space_key, user_key)
# Grant permissions to user in the given space.
confluence.set_permissions_to_user_for_space(space_key, user_key, operations=None)
# Remove permissions granted to user for the given space
confluence.remove_permissions_from_user_for_space(space_key, user_key)
# Add permissions to a space
confluence.add_space_permissions(space_key, user_key, group_name, operations)
# Remove permissions from a space
confluence.remove_space_permissions(space_key, user_key, group_name, permission)
Users and Groups¶
# Get all groups from Confluence User management
confluence.get_all_groups(start=0, limit=1000)
# Get information about a user through username
confluence.get_user_details_by_username(username, expand=None)
# Get information about a user through user key
confluence.get_user_details_by_userkey(userkey, expand=None)
# Change a user's password
confluence.change_user_password(username, password)
# Change calling user's password
confluence.change_my_password(oldpass, newpass)
# Add given user to a group
confluence.add_user_to_group(username, group_name)
# Remove given user from a group
confluence.remove_user_from_group(username, group_name)
CQL¶
# ``cql()`` returns one result page. CQL search results wrap a page in
# ``result["content"]``, so expand the nested path, not ``body.storage``.
response = confluence.cql(
'space = "TEAM" and type = page',
limit=25,
expand="content.body.storage",
)
for result in response.get("results", []):
storage = result["content"]["body"]["storage"]["value"]
# Cloud pagination is cursor-based. This iterator follows ``_links.next``
# for every page; do not increment ``start`` yourself.
for result in confluence.iter_cql(
'space = "TEAM" and type = page', limit=25, expand="content.body.storage"
):
storage = result["content"]["body"]["storage"]["value"]
# Materialize every matching result only when an in-memory list is needed.
all_results = confluence.cql_all('space = "TEAM" and type = page', limit=25)
iter_cql() and cql_all() work for Cloud and Server/Data Center. Cloud
follows its cursor link, while Server/Data Center retains its offset-based
pagination semantics. The Cloud V2 client (ConfluenceV2) exposes the same
pair on the api/v2/search endpoint:
for result in confluence_v2.iter_cql('space.id = "123456" and type = page', limit=25):
process(result)
all_results = confluence_v2.cql_all('space.id = "123456" and type = page', limit=25)
Other actions¶
# Clean all caches from cache management
confluence.clean_all_caches()
# Clean caches from cache management
# e.g.
# com.gliffy.cache.gon
# org.hibernate.cache.internal.StandardQueryCache_v5
confluence.clean_package_cache(cache_name='com.gliffy.cache.gon')
# Convert to Confluence XHTML format from wiki style
confluence.convert_wiki_to_storage(wiki)
# Get page history
confluence.history(page_id)
# Get content history by version number
confluence.get_content_history_by_version_number(content_id, version_number)
# Remove content history. It works as experimental method
confluence.remove_content_history(page_id, version_number)
# Compare content and check is already updated or not
confluence.is_page_content_is_already_updated(page_id, body)
# Add inline task setting checkbox method
confluence.set_inline_tasks_checkbox(page_id, task_id, status)
Consistent return values¶
For Server and Data Center, get_tables_from_page always returns a
dictionary with page_id, number_of_tables_in_page, and
tables_content. Pages without tables use a count of zero and an empty
list. download_attachments_from_page likewise returns an empty dictionary
in memory mode, or {"attachments_downloaded": 0, "path": ...} on disk
when no attachments match.
attach_content and update_page raise ApiNotFoundError when the
target page cannot be resolved instead of returning None. Title lookups
remain search-result responses; an empty results collection means that no
matching page exists.
Content history¶
get_content_history_by_version_number and the Server/Data Center
history-removal methods use the supported
/rest/api/content/{id}/version/{number} endpoint. Cloud history removal
uses the equivalent V1 content endpoint under /wiki; the retired
/rest/experimental route is not used. remove_page_history_keep_version
also tolerates historical gaps, so rerunning it after a partial cleanup does
not fail on an already-deleted version.
For Confluence Cloud V2, use get_page_versions or get_page_version to
read page history. The published V2 API does not provide a delete-version
operation, so deletion requires the compatible V1 endpoint and appropriate
permission.
Scoped Cloud API tokens¶
Scoped Confluence Cloud API tokens use the Atlassian API gateway and the v2
API. Pass the gateway URL containing the cloud ID; Confluence selects the
v2 Cloud client automatically and does not append /wiki.
confluence = Confluence(
url="https://api.atlassian.com/ex/confluence/<cloud-id>",
username="user@example.com",
password="scoped-api-token",
cloud=True,
)
page = confluence.get_page_by_id("<page-id>")
Confluence Cloud databases¶
Confluence Cloud v2 supports database lifecycle metadata: create, retrieve by
ID, and move to trash. Use ConfluenceV2 (or a gateway URL as above) for
these endpoints. The public API does not currently expose database records,
fields, views, or queries.
from atlassian import ConfluenceV2
confluence = ConfluenceV2(
url="https://your-domain.atlassian.net/wiki",
username="user@example.com",
password="api-token",
)
database = confluence.create_database(
space_id="<space-id>",
title="Release tracker",
parent_id="<parent-page-or-folder-id>",
private=False,
)
details = confluence.get_database(database["id"], include_properties=True)
confluence.delete_database(database["id"])
Scoped tokens require the corresponding write:database:confluence,
read:database:confluence, or delete:database:confluence scope.
Confluence Cloud folders¶
Confluence Cloud v2 supports creating, retrieving, and moving folders to
trash. A folder may have a page or another folder as its parent. Use
ConfluenceV2 (or a gateway URL as above).
folder = confluence.create_folder(
space_id="<space-id>",
title="Release assets",
parent_id="<parent-page-or-folder-id>",
)
details = confluence.get_folder(folder["id"], include_direct_children=True)
confluence.delete_folder(folder["id"])
Scoped tokens require the corresponding write:folder:confluence,
read:folder:confluence, or delete:folder:confluence scope.
Additional Cloud v2 resources¶
The Cloud v2 client also exposes administrative and workspace operations from the current OpenAPI contract:
admin_key = confluence.get_admin_key()
permissions = confluence.get_space_permissions(limit=25)
roles = confluence.get_space_roles(space_id="<space-id>", limit=25)
users = confluence.bulk_get_users({"accountIds": ["<account-id>"]})
policies = confluence.get_data_policy_spaces(ids=["<space-id>"])
Global comments are available through get_global_footer_comments and
get_global_inline_comments. Their child, likes, operations, and version
resources are exposed by the corresponding *_v2 helpers.
Cloud group members¶
Confluence Cloud group membership uses the group ID, not its display name.
The API returns group IDs from get_all_groups. The legacy Server/Data
Center methods continue to use group names.
for group in confluence.get_all_groups(start=0, limit=1000):
members = confluence.get_all_members(group["id"])
License endpoints¶
get_license_details and the related license-seat methods are available for
Confluence Server and Data Center only. Confluence Cloud does not expose an
equivalent license REST API; Cloud clients receive ApiNotAcceptable instead
of an HTTP 404.