I’m trying to use the Confluence REST API v2 API to create a new wiki page whose body is in the atlas_doc_format. I can’t seem to get anything except a 400 Bad Request response with a body of Invalid message. Does anyone have any suggestions on what I’m doing wrong with the request?
The POST request is being made to https://(my org).atlassian.net/wiki/api/v2/pages, with the following request body (formatted here for readability):
Figured out yesterday that the body value needs to be JSON encoded, not passed as the underlying object. The correct form is like the following (value has been abbreviated).
Very weird. The value entry is a sort of ‘escaped’ JSON. The same problem happens when you try to get the body of a page. You either get XML or you get this escaped JSON as a string. But no usable JSON.
It’s a JSON encoded string of the JSON serialized object for the ADF.
Given an ADF object, you’d serialize it to the JSON representation, then assign that string as the value.
As @GerbenWierda noted, the same thing happens when you get the body of a page in ADF format. You have to treat the body value as a JSON serialized value and decode it to get the actual object. That’s actually what clued me in to the need to do the opposite when creating/updating a page.
Here’s an extension of the Python example in the Create page documentation showing an ADF document being created and encoded.
In short, the key is to JSON encode the ADF body object and assign that as the body value in the request.
import json
from pyadf.document import Document
import requests
from requests.auth import HTTPBasicAuth
url = "https://{your-domain}/wiki/api/v2/pages"
auth = HTTPBasicAuth("email@example.com", "<api_token>")
headers = {
"Accept": "application/json",
"Content-Type": "application/json"
}
doc = Document()
doc.paragraph().text("Hello, world!")
# This is the ADF document body as an actual object.
body = doc.to_doc()["body"]
# The key is to serialize the ADF body as JSON for the create/update request,
# not assign the unserialized object directly as the body value.
payload = {
"spaceId": 15,
"status": "current",
"title": "Example",
"parentId": 34,
"body": {
"representation": "atlas_doc_format",
"value": json.dumps(body), # Serialize the ADF body as JSON.
}
}
# The entire payload is then serialized as JSON for the create/update request.
payload_json = json.dumps(payload)
response = requests.request(
"POST",
url,
data=payload_json,
headers=headers,
auth=auth
)
This also means that the reverse is true when getting a page in ADF format. You’d need to JSON decode the response, get the body value string, and then JSON decode that in order to get the ADF object.