Confluence API v2 not updating page

Hi everyone, I am having problems with the new Confluence API. I am trying to update my page using the v2 endpoint PUT /wiki/api/v2/pages/{id} but I get back the error:
{ errors: [ { status: 400, code: 'INVALID_MESSAGE', title: 'Invalid message', detail: null } ] }

This is my request:

 const response = await api.asApp().requestConfluence(route`/wiki/api/v2/pages/${id}`, {
          method: 'PUT',
          headers: {
            'Accept': 'application/json',
            'Content-Type': 'application/json'
          },
          body:
          `{
            "id": "${id}",
            "status": "${pageStatus}",
            "title": "${pageTitle}",
            "spaceId": "${spaceId}",
            "body":  {
              "representation": "atlas_doc_format",
              "value": ${fakeData}
            },
            "version": {
              "number": ${docVersion + 1}
            }
          }`
        });

According to the documentation, a message for your version is not needed. However, when I do add one I still get the same error message. Has anyone else had this problem?

Hi @ImogenDrews1 - It could be that body.value is not a valid string type. The ADF body value should be passed in as an escaped string.

Could you try the above again with the same body value you receive from https://<tenant>.atlassian.net/wiki/api/v2/pages/<page-id>?body-format=atlas_doc_format? Thanks!

I have the same issue on my side.
I tried with the ADF example given by atlassian here

{
  "version": 1,
  "type": "doc",
  "content": [
    {
      "type": "paragraph",
      "content": [
        {
          "type": "text",
          "text": "Hello "
        },
        {
          "type": "text",
          "text": "world",
          "marks": [
            {
              "type": "strong"
            }
          ]
        }
      ]
    }
  ]
}

Hi @PierrickChevallay1 - could you try passing the ADF as a JSON escaped value?

For example, you could pass the below in this way:

"body": {
    "value": "{\r\n  \"version\": 1,\r\n  \"type\": \"doc\",\r\n  \"content\": [\r\n    {\r\n      \"type\": \"paragraph\",\r\n      \"content\": [\r\n        {\r\n          \"type\": \"text\",\r\n          \"text\": \"Hello \"\r\n        },\r\n        {\r\n          \"type\": \"text\",\r\n          \"text\": \"world\",\r\n          \"marks\": [\r\n            {\r\n              \"type\": \"strong\"\r\n            }\r\n          ]\r\n        }\r\n      ]\r\n    }\r\n  ]\r\n}",
    "representation": "atlas_doc_format"
}

Hello @SimonKliewer ,
I figure out what was the problem. It seems the ADF json should be dump into a string.
So basically, if I take the example from the doc:

# This code sample uses the 'requests' library:
# http://docs.python-requests.org
import requests
from requests.auth import HTTPBasicAuth
import json

url = "https://{your-domain}/wiki/api/v2/pages/{id}"

auth = HTTPBasicAuth("email@example.com", "<api_token>")

headers = {
  "Accept": "application/json",
  "Content-Type": "application/json"
}

adf_body= {
  "version": 1,
  "type": "doc",
  "content": [
    {
      "type": "paragraph",
      "content": [
        {
          "type": "text",
          "text": "Hello "
        },
        {
          "type": "text",
          "text": "world",
          "marks": [
            {
              "type": "strong"
            }
          ]
        }
      ]
    }
  ]
}

payload = json.dumps( {
  "id": "<string>",
  "status": "current",
  "title": "<string>",
  "spaceId": "<string>",
  "body": {
    "representation": "atlas_doc_format",
    "value": json.dumps(adf_body)
  },
  "version": {
    "number": 47,
    "message": "<string>"
  }
} )

response = requests.request(
   "PUT",
   url,
   data=payload,
   headers=headers,
   auth=auth
)

print(json.dumps(json.loads(response.text), sort_keys=True, indent=4, separators=(",", ": ")))

BR
Pierrick

2 Likes

Hello @PierrickChevallay1,
This is the solution! Thank you so much for figuring this out - I recently had to use this endpoint again and still couldn’t make it work. It’s a pretty strange workaround, would be great if it was mentioned in the documentation.

1 Like