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 --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');
});
"
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}'
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
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);
});
"
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`);
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")