Showing results for 
Search instead for 
Did you mean: 
Sign up Log in

Next challenges

Recent achievements

  • Global
  • Personal


  • Give kudos
  • Received
  • Given


  • Global

Trophy case

Kudos (beta program)

Kudos logo

You've been invited into the Kudos (beta program) private group. Chat with others in the program, or give feedback to Atlassian.

View group

It's not the same without you

Join the community to find out what other Atlassian users are discussing, debating and creating.

Atlassian Community Hero Image Collage

Confluence server REST API update page removes all macros?


I need to convert about 100 pages, their Page Properties is not in right format. I managed to convert table in Page Properties and table is updated to back page with REST API.

However, after page has been updated there is no macro's anymore. Page properties, Page tree and Expand macro's are gone.

What could be the reason for this? Wrong value in body': { 'storage': { 'representation': 'storage' ?


2 answers

1 accepted

0 votes
Answer accepted

Hi @allecti,

Have you checked that the macros are still part of the storage format you send to the server?

Can you please add your REST request and some example payload, so I can have a closer look at it?

Best, Tobias

This is what I get originally:

{u'status': u'current', u'body': {u'_expandable': {u'export_view': u'', u'styled_view': u'', u'editor': u'', u'anonymous_export_view': u'', u'view': u''}, u'storage': {u'_expandable': {u'content': u'/rest/api/content/68335322'}, u'representation': u'storage', u'value': u'<p class="auto-cursor-target"><br /></p><ac:structured-macro ac:name="details" ac:schema-version="1" ac:macro-id="12aaf1ce-2b17-443c-8bae-ed3bb63adae4"><ac:rich-text-body><p class="auto-cursor-target"><br /></p><table class="wrapped fixed-table"><colgroup><col style="width: 166.0px;" /><col style="width: 132.0px;" /><col style="width: 65.0px;" /><col style="width: 159.0px;" /></colgroup><tbody><tr><th>Status</th><td><div class="content-wrapper"><p><ac:structured-macro ac:name="status" ac:schema-version="1" ac:macro-id="23bda9ed-398e-4543-b38f-b2136db1a9dc"><ac:parameter ac:name="colour">Yellow</ac:parameter><ac:parameter ac:name="title">Draft</ac:parameter></ac:structured-macro></p></div></td><td class="highlight-grey" data-highlight-colour="grey"><div class="content-wrapper"><p><strong>Rev</strong></p></div></td><td><div class="content-wrapper"><p>0.3</p></div></td></tr><tr><th class="highlight-grey" colspan="1" data-highlight-colour="grey">Range of validity</th><td colspan="3"><div class="content-wrapper"><p>general</p></div></td></tr><tr><th colspan="1">Period of validity</th><td colspan="1"><br /></td><td colspan="1" style="text-align: center;">-</td><td colspan="1"><br /></td></tr><tr><th colspan="1">Owner</th><td colspan="3"><ac:link><ri:user ri:userkey="ff808181604b387d0160e550b6320008" /></ac:link></td></tr></tbody>


Python function to read data:

def read_data_storage(auth, page_id): 
= '{base}/{page_id}?,macro'.format(base=BASE_URL, page_id=page_id)
= requests.get( url, auth=auth, headers={'Content-Type': 'application/json', 'USER-AGENT': USER_AGENT} )
return r

After read I will do

json_text = read_data_storage(auth, options.pageid).text
= json.loads(json_text)
html_storage_txt = json2['body']['storage']['value']

 data = html_storage_text.encode('utf-8')

<p class="auto-cursor-target"><br /></p>
<ac:structured-macro ac:name="details" ac:schema-version="1" ac:macro-id="12aaf1ce-2b17-443c-8bae-ed3bb63adae4">
<p class="auto-cursor-target"><br /></p><table class="wrapped fixed-table">

I am using lxml to modify. 

tree = lxml.html.fromstring(data)

..... update 1st table content ....

html_string = lxml.html.tostring(tree, pretty_print=True)

<p class="auto-cursor-target"><br></p>
<structured-macro ac:name="details" ac:schema-version="1" ac:macro-id="12aaf1ce-2b17-443c-8bae-ed3bb63adae4"><rich-text-body><p class="auto-cursor-target"><br></p>
<table class="wrapped fixed-table">

write_data_storage(auth, html_string, options.pageid)

 def write_data_storage(auth, html, page_id, title = None): 
= get_page_info(auth, page_id)
ver = int(info['version']['number']) + 1
ancestors = get_page_ancestors(auth, page_id)
anc = ancestors[-1]
del anc['_links']
del anc['_expandable']
del anc['extensions']
if title is not None: info['title'] = title
data = { 'id': str(page_id), 'type': 'page', 'title': info['title'],
'version': {'number': ver}, 'ancestors': [anc],
'body': { 'storage':
'representation': 'storage',
'value': str(html),



data = json.dumps(data)
url = '{base}/{page_id}'.format(base=BASE_URL, page_id=page_id)
our_headers = {'Content-Type': 'application/json', 'USER-AGENT': USER_AGENT}
r = requests.put( url, data=data, auth=auth, headers=our_headers )
print "Wrote '%s' version %d" % (info['title'], ver) print "URL: %s%d" % (VIEW_URL, page_id)
return ""


Actually I have been playing it around now a while, trying to find out if storage / view representation matters. Now I get 400 error, need to figure out that.

Before I managed to update page but macro's were dropped out.

it would be nice to get even hints if I am doing something totally wrong. 

Hi @allecti,

The following request works for me:

"title":"new page",
"body": {
"storage": {
"value": "<p>This is the updated text for the new page</p>",
"version":{"number": 44}

The major difference in my request is that I do not use the ancestors parameter and have a space parameter set.

Furthermore I would have a closer look into any html encode/decode operations.

The best is to try the requests in Postman or the Confluence Rest API browser first.

Best, Tobias

Thanks Tobias!

Yes, it is something to do now with encode/decode operations. My code works if I will use original data I got from Postman and I just update table part of that -> everything is just like it should be. 

Like Tobias Anstett _K15t_ likes this

@allecti  hi,

can you share any code how u update table without encode 

Actually found out that it is better to use request.content instead of request.text that seems to convert data and specially encoding it to string.

Everything started to work ok when I changed:

json_text = read_data_storage(auth, options.pageid).text


json_text = read_data_storage(auth, options.pageid).content

Suggest an answer

Log in or Sign up to answer
Community showcase
Published in Confluence

Announcing Team Calendars in Confluence Data Center

Hi Community! We're thrilled to share that Team Calendars for Confluence is now a built-in feature for Confluence Data Center releases 7.11 and beyond.  A long time favorite,  Team Cale...

59 views 0 3
Read article

Community Events

Connect with like-minded Atlassian users at free events near you!

Find an event

Connect with like-minded Atlassian users at free events near you!

Unfortunately there are no Community Events near you at the moment.

Host an event

You're one step closer to meeting fellow Atlassian users at your local event. Learn more about Community Events

Events near you