Examples

All examples use these environment variables:

CLOUD_ID="your-cloud-id"
APP_ID="0def1d4f-1593-4dd0-99a3-a098b3959067"
ENV_ID="796457c9-9c03-4382-b44f-d19571068ece"   # production
TOKEN="your-access-token"

cURL

Export a space (bulk)

curl --request POST \
  --url "https://api.atlassian.com/svc/confluence/${CLOUD_ID}/apps/${APP_ID}_${ENV_ID}/bulkExport" \
  --header "Authorization: Bearer ${TOKEN}" \
  --header "Content-Type: application/json" \
  --data '{"spaceKey": "MYSPACE", "maxPages": 100}' \
  | node -e "
    let d = '';
    process.stdin.on('data', c => d += c);
    process.stdin.on('end', () => {
      const { zipBase64, pageCount } = JSON.parse(d);
      require('fs').writeFileSync('export.zip', Buffer.from(zipBase64, 'base64'));
      console.log('Saved export.zip —', pageCount, 'pages');
    });
  "

Export a page tree with attachments

curl --request POST \
  --url "https://api.atlassian.com/svc/confluence/${CLOUD_ID}/apps/${APP_ID}_${ENV_ID}/bulkExport" \
  --header "Authorization: Bearer ${TOKEN}" \
  --header "Content-Type: application/json" \
  --data '{"pageId": "123456", "bulkExport": true, "maxPages": 100, "includeAttachments": true}'

Export a single page (plain text)

curl --request POST \
  --url "https://api.atlassian.com/svc/confluence/${CLOUD_ID}/apps/${APP_ID}_${ENV_ID}/singleExport" \
  --header "Authorization: Bearer ${TOKEN}" \
  --header "Content-Type: application/json" \
  --data '{"pageId": "123456"}' \
  > my-page.md

Export a single page with attachments (ZIP)

curl --request POST \
  --url "https://api.atlassian.com/svc/confluence/${CLOUD_ID}/apps/${APP_ID}_${ENV_ID}/singleExport" \
  --header "Authorization: Bearer ${TOKEN}" \
  --header "Content-Type: application/json" \
  --data '{"pageId": "123456", "includeAttachments": true}' \
  | node -e "
    let d = '';
    process.stdin.on('data', c => d += c);
    process.stdin.on('end', () => {
      const { zipBase64, title } = JSON.parse(d);
      require('fs').writeFileSync('export.zip', Buffer.from(zipBase64, 'base64'));
      console.log('Saved export.zip for:', title);
    });
  "

Node.js

Full example with automatic token refresh:

import fs from 'fs';

const TOKEN_FILE    = './tokens.json';
const CLIENT_ID     = process.env.ATLASSIAN_CLIENT_ID;
const CLIENT_SECRET = process.env.ATLASSIAN_CLIENT_SECRET;
const CLOUD_ID      = process.env.CONFLUENCE_CLOUD_ID;
const APP_ID        = '0def1d4f-1593-4dd0-99a3-a098b3959067';
const ENV_ID        = '796457c9-9c03-4382-b44f-d19571068ece';

function loadTokens() {
  return JSON.parse(fs.readFileSync(TOKEN_FILE, 'utf8'));
}

function saveTokens(tokens) {
  fs.writeFileSync(TOKEN_FILE, JSON.stringify(tokens, null, 2));
}

async function getValidToken() {
  const tokens = loadTokens();
  const payload = JSON.parse(Buffer.from(tokens.access_token.split('.')[1], 'base64').toString());

  if (Date.now() < payload.exp * 1000 - 5 * 60 * 1000) {
    return tokens.access_token;
  }

  const res = await fetch('https://auth.atlassian.com/oauth/token', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      grant_type:    'refresh_token',
      client_id:     CLIENT_ID,
      client_secret: CLIENT_SECRET,
      refresh_token: tokens.refresh_token,
    }),
  });

  const newTokens = await res.json();
  if (!newTokens.access_token) throw new Error(`Token refresh failed: ${JSON.stringify(newTokens)}`);

  saveTokens({ access_token: newTokens.access_token, refresh_token: newTokens.refresh_token });
  return newTokens.access_token;
}

const token = await getValidToken();
const res = await fetch(
  `https://api.atlassian.com/svc/confluence/${CLOUD_ID}/apps/${APP_ID}_${ENV_ID}/bulkExport`,
  {
    method: 'POST',
    headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' },
    body: JSON.stringify({ spaceKey: 'MYSPACE', maxPages: 100 }),
  }
);

const { zipBase64, pageCount } = await res.json();
fs.writeFileSync('export.zip', Buffer.from(zipBase64, 'base64'));
console.log(`Exported ${pageCount} pages`);

Python

Full example with automatic token refresh:

import json, time, base64, os, requests
from pathlib import Path

TOKEN_FILE    = Path('tokens.json')
CLIENT_ID     = os.environ['ATLASSIAN_CLIENT_ID']
CLIENT_SECRET = os.environ['ATLASSIAN_CLIENT_SECRET']
CLOUD_ID      = os.environ['CONFLUENCE_CLOUD_ID']
APP_ID        = '0def1d4f-1593-4dd0-99a3-a098b3959067'
ENV_ID        = '796457c9-9c03-4382-b44f-d19571068ece'

def load_tokens():
    return json.loads(TOKEN_FILE.read_text())

def save_tokens(tokens):
    TOKEN_FILE.write_text(json.dumps(tokens, indent=2))

def get_valid_token():
    tokens = load_tokens()
    payload = json.loads(base64.b64decode(tokens['access_token'].split('.')[1] + '=='))

    if time.time() < payload['exp'] - 300:
        return tokens['access_token']

    r = requests.post('https://auth.atlassian.com/oauth/token', json={
        'grant_type':    'refresh_token',
        'client_id':     CLIENT_ID,
        'client_secret': CLIENT_SECRET,
        'refresh_token': tokens['refresh_token'],
    })
    r.raise_for_status()
    new_tokens = r.json()

    save_tokens({'access_token': new_tokens['access_token'], 'refresh_token': new_tokens['refresh_token']})
    return new_tokens['access_token']

token = get_valid_token()
resp = requests.post(
    f'https://api.atlassian.com/svc/confluence/{CLOUD_ID}/apps/{APP_ID}_{ENV_ID}/bulkExport',
    headers={'Authorization': f'Bearer {token}', 'Content-Type': 'application/json'},
    json={'spaceKey': 'MYSPACE', 'maxPages': 100},
)
data = resp.json()
Path('export.zip').write_bytes(base64.b64decode(data['zipBase64']))
print(f"Exported {data['pageCount']} pages")