atlassian-cli is an independent, community open-source project, not affiliated with, endorsed by, or sponsored by Atlassian, and is not Atlassian's official CLI (acli). Product names are used only to identify compatibility.
What the Confluence REST API is
The Confluence REST API is Atlassian's HTTP interface for reading and writing Confluence Cloud content: pages, blog posts, spaces, attachments, labels, and comments. Anything you can do in the web UI, you can drive over HTTPS with a token and a JSON body. For Confluence Cloud the current version is v2, served under https://your-domain.atlassian.net/wiki/api/v2. The /wiki prefix is specific to Confluence, so do not drop it.
People reach for the API to automate documentation work: syncing release notes from a repo, publishing generated reports, bulk-labeling stale pages, or pulling a space into a backup. This guide covers the parts you actually need to get productive: the v2 resource model, how authentication works with an API token, real curl examples you can paste into a terminal, and pagination. Then it shows how atlassian-cli wraps the same endpoints so you rarely have to hand-roll requests at all.
How the Confluence REST API v2 is structured
There are two live versions of the Confluence REST API, and it helps to know which one you are talking to. v2 is the current, recommended surface for new integrations. v1 is older but still available, and it still owns a few features that v2 has not migrated yet. The most important gap: CQL content search still lives in v1.
| Aspect | REST API v2 | REST API v1 |
|---|---|---|
| Base path | /wiki/api/v2 |
/wiki/rest/api |
| Pagination | Cursor-based (_links.next) |
Offset-based (start / limit) |
| Space reference | Numeric spaceId |
Space key or ID |
| CQL search | Not yet covered | /rest/api/content/search |
| Status | Current, use for new work | Legacy, still supported |
In practice many teams use both at once: v2 for reading and writing pages and spaces, v1 for CQL search. That is normal and expected. The one thing to avoid is building a brand-new integration entirely on v1 when v2 already covers your resource.
Authenticating with an API token
The simplest method for scripts is HTTP Basic authentication with your Atlassian account email and an API token. Create a token at id.atlassian.com under Security > API tokens, then pass it as the password. For user-facing applications you would use OAuth 2.0 instead, but for automation and CI, a token is the shortest path.
Set your credentials as environment variables so you never paste a secret into a shared script:
# Store credentials once, per shell session
export CONF_EMAIL="you@example.com"
export CONF_TOKEN="your_api_token"
export CONF_BASE="https://your-domain.atlassian.net/wiki"
# List the first 25 pages you can see
curl -s -u "$CONF_EMAIL:$CONF_TOKEN" \
"$CONF_BASE/api/v2/pages?limit=25" \
-H "Accept: application/json"
The -u "email:token" flag tells curl to build the Basic auth header for you. If the call returns 401, the token or email is wrong; a 403 means the credentials are valid but lack permission for that resource. Treat the token like a password: rotate it if it leaks, and prefer a dedicated service account for automation.
Core v2 endpoints, with examples
Most Confluence automation touches four resources: spaces, pages, page bodies, and versions. Here are the requests you will use most.
Resolve a space key to an ID
Because v2 references spaces by numeric ID rather than key, you often start by looking up the ID for a human-friendly key like DEV:
curl -s -u "$CONF_EMAIL:$CONF_TOKEN" \
"$CONF_BASE/api/v2/spaces?keys=DEV" \
-H "Accept: application/json"
Read a page, with its body
By default v2 does not return page bodies. Ask for one explicitly with body-format. The common representations are storage (Confluence storage XHTML) and atlas_doc_format (ADF JSON):
curl -s -u "$CONF_EMAIL:$CONF_TOKEN" \
"$CONF_BASE/api/v2/pages/12345?body-format=storage" \
-H "Accept: application/json"
Create a page
Creating a page is a POST to /pages with the numeric spaceId, a status, a title, and a body:
curl -s -u "$CONF_EMAIL:$CONF_TOKEN" \
-X POST "$CONF_BASE/api/v2/pages" \
-H "Content-Type: application/json" \
-d '{
"spaceId": "65601",
"status": "current",
"title": "Release Notes 1.2",
"body": { "representation": "storage", "value": "<p>Shipped.</p>" }
}'
Update a page
Updates are the one place people trip. v2 requires you to send the new version number, which must be exactly one higher than the current version, along with the id, status, and title. If you send the wrong version, the API rejects the write to protect against overwriting concurrent edits:
curl -s -u "$CONF_EMAIL:$CONF_TOKEN" \
-X PUT "$CONF_BASE/api/v2/pages/12345" \
-H "Content-Type: application/json" \
-d '{
"id": "12345",
"status": "current",
"title": "Release Notes 1.2",
"body": { "representation": "storage", "value": "<p>Updated.</p>" },
"version": { "number": 2 }
}'
Search with CQL (v1)
When you need to find content by query rather than fetch it by ID, use the v1 search endpoint. CQL (Confluence Query Language) is the same syntax the UI's advanced search uses:
curl -s -u "$CONF_EMAIL:$CONF_TOKEN" \
"$CONF_BASE/rest/api/content/search?cql=space%3DDEV%20and%20type%3Dpage&limit=25" \
-H "Accept: application/json"
Pagination and body formats
v2 uses cursor-based pagination. A list response includes a _links.next field holding a relative URL with an opaque cursor. To walk every page of results, keep following _links.next until it is absent:
# First page returns something like:
# { "results": [ ... ], "_links": { "next": "/wiki/api/v2/pages?cursor=eyJpZ..." } }
# Follow the cursor for the next page
curl -s -u "$CONF_EMAIL:$CONF_TOKEN" \
"https://your-domain.atlassian.net/wiki/api/v2/pages?cursor=eyJpZ..." \
-H "Accept: application/json"
Do not try to construct the cursor yourself or assume it is a page number. Treat it as opaque: read it from the previous response and pass it back verbatim. This is the biggest behavioral difference from v1, which paginated with numeric start and limit offsets.
On body formats, pick the representation that matches how you produce content. If you write raw Confluence markup, use storage. If you build content as structured ADF, use atlas_doc_format. For read-only display you can request view, which returns rendered HTML. Handling this parsing, plus the cursor loop and the version-increment dance, is exactly the sort of glue code that a wrapper removes.
Skip the curl: atlassian-cli as a wrapper
Once you have written the same auth header, cursor loop, and JSON parser a few times, the appeal of a wrapper is obvious. atlassian-cli is a single Rust binary that maps directly onto these endpoints. It stores your credentials once, follows pagination for you, and prints clean tables or JSON.
A note on naming: atlassian-cli is an independent, community open-source project. It is not Atlassian's official CLI (acli) and is not affiliated with, endorsed by, or sponsored by Atlassian. Use the official acli if you want first-party vendor support; use atlassian-cli if you want a single free binary spanning Jira, Confluence, Bitbucket, and Jira Service Management with the same flag conventions everywhere.
Authenticate once, then the token lives in a named profile:
atlassian-cli auth login \
--profile work \
--base-url https://your-domain.atlassian.net \
--email you@example.com \
--token $CONF_TOKEN \
--default
From there, the same operations you saw above become one-liners. No base path, no _links.next loop, no version arithmetic:
# List pages in a space (pagination handled for you)
atlassian-cli confluence page list --space DEV --limit 25
# Read a page by ID
atlassian-cli confluence page get 12345
# Create a page
atlassian-cli confluence page create \
--space DEV \
--title "Release Notes 1.2" \
--body "<p>Shipped.</p>"
# CQL search, same query language as the raw v1 endpoint
atlassian-cli confluence search cql "space = DEV and type = page" --limit 25
Every command accepts a global --format flag, so you can get JSON, CSV, YAML, or a quiet exit-code-only mode. That makes the CLI a drop-in for scripts that would otherwise curl the API and pipe through jq:
# Machine-readable output straight into jq
atlassian-cli confluence page list --space DEV \
--format json | jq '.[].title'
For heavier maintenance work there are bulk verbs too: atlassian-cli confluence bulk add-labels --cql "space = DEV" --labels docs,reviewed --dry-run previews a mass label change before it touches anything, and confluence bulk export writes a whole space to a JSON file. See the full command list in the command reference.
When to call the API directly vs the CLI
Both approaches hit the same Confluence REST API. The choice is about how much glue you want to own.
Call the REST API directly when...
You are building a long-running service, you need OAuth 2.0 rather than a token, you must hit a niche endpoint the CLI does not expose, or you want fine-grained control over headers, retries, and error handling inside your own codebase.
Use atlassian-cli when...
You are scripting from the terminal or CI, you want auth, pagination, and JSON parsing handled for you, or you want one consistent interface across Confluence, Jira, Bitbucket, and JSM. It is the fastest path from idea to working automation.
A common pattern is to prototype with the CLI, confirm the workflow, and only drop down to raw HTTP if you later need something the CLI does not cover. To go deeper on either side, see the Confluence API from the CLI walkthrough and the Confluence automation guide, or browse the Confluence CLI reference.
Drive Confluence without the boilerplate
Install the single-binary atlassian-cli and talk to the Confluence REST API in one line.
Try atlassian-cliFAQ
What is the base URL for the Confluence REST API?
For Confluence Cloud, the current version (v2) lives under https://your-domain.atlassian.net/wiki/api/v2. The older v1 API is served from https://your-domain.atlassian.net/wiki/rest/api and is still available. Replace your-domain with your site's subdomain, and note the /wiki prefix, which is specific to Confluence.
How do I authenticate with the Confluence REST API?
The simplest method for scripts is HTTP Basic auth with your Atlassian account email and an API token. Create a token at id.atlassian.com under Security, then send it as the password with curl -u "email:token". For user-facing apps, use OAuth 2.0 instead. Never hard-code a token in a shared script; read it from an environment variable.
What is the difference between the Confluence REST API v1 and v2?
v2 (/wiki/api/v2) is the current API for new work: it uses numeric identifiers, cursor-based pagination via a _links.next field, and a cleaner resource model for pages, spaces, and attachments. v1 (/wiki/rest/api) uses offset pagination and still owns some features that v2 has not covered yet, most notably CQL content search. Many teams use both side by side.
Can I use the Confluence REST API without writing curl scripts?
Yes. A CLI wrapper handles the endpoint paths, auth headers, pagination, and JSON parsing for you. With atlassian-cli you run commands like atlassian-cli confluence page list --space DEV or atlassian-cli confluence page create --space DEV --title "Notes" --body "<p>Hi</p>", and add --format json to get machine-readable output for piping into jq.