In my previous post I explored how to access the Confluence Cloud Space Permissions API endpoint. 

This Python script extends that, and gives a user a permission set in all Spaces in Confluence. This could be useful if you wanted to give one person Administrative rights on all Spaces in Confluence, for example.

Note that the user must first have READ/SPACE permission before any other permissions can be granted.

 from requests.models import Response
import requests
import json
headers = {
    'Authorization': 'Basic <Base-64 encoded username and password>',
    'Content-Type': 'application/json',
    'Accept': 'application/json',
userID = '<user ID (not name)>'
resp = requests.get(url, headers=headers)
data = json.loads(resp.text)
for lines in data["results"]:
  url="https://<url>"+lines["key"] + '/permission'
  dictionary = {"subject":{"type":"user","identifier": userID},"operation":{"key":"read","target":"space"},"_links":{}}
  data = data=json.dumps(dictionary)
      response =, headers=headers, data=data)
    print("Could not add permissions to Space " + lines["key"])   

There’s a great deal of information on the internet about managing Confluence Space permissions with scripts, and how there’s no REST endpoint for it, and how it’s basically impossible.

This is incorrect.

There’s also a lot of information about using the JSONRPC or XMLRPC APIs to accomplish this.   These APIs are only available on Server/DC. In the Cloud they effectively don’t exist, so this is yet more misinformation.

So why all the confusion?

There’s a lot of outdated information out there that floats around and doesn’t disappear even after it stops being correct or relevant. This is one of the major struggles I had when I started learning how to write scripts to interact with Jira and Confluence.    Much of the information used to be relevant, but five or six or ten years later it only serves to distract people looking for a solution. That’s one of the major reasons I started this blog in the first place.

Specific to this instance, another reason for confusion is that the documentation for the REST API does outline an endpoint for Confluence Space permission management, but it includes some very strict limitations that could easily be misinterpreted.

The limitation is this: the

You can easily remove all permissions from a Confluence DC Space, or a Confluence Cloud Space.  Confluence Server, though? You’re out of luck.

Imagine you migrated from Confluence Cloud to Confluence Server, and you wanted to remove all permissions on a Space (except  for maybe “View Space”).  That’s a whole lot of manually clicking, unless you script it.  You’re going to need ScriptRunner for this.

The script below takes two inputs: a Space key, and a username.  It needs the username of someone on the Space with Admin access, because Confluence will not let you remove EVERYONE  with admin access from the Space.

Someone gets left behind.


Okay so it takes those two pieces of information as variables.  It then makes use of two arrays. The first array is a prescribed selection of the permissions you’d like removed from the Space. Want to let everyone keep the View Space permission type? Take it out of the List!
The second array is generated by the script. It’s a list of every username and group name with some kind of permission on the Space.

We then nest two loops, and iterate through the permission types and usernames.  For each permission type,


There may come a day where you need to script the migration of permissions from one Confluence Space to another.

The permissions of a Confluence Space can be retrieved and treated as collection of objects.  This allows us to easily pass them on to a source page as a new set of permissions.

The Code

We’re using the Soap Service to affect change in the permissions of a Space.  After using the ComponentLocator to declare the SpaceSoapService, we retrieve the source Space as an object.  We do the same for the destination source.

The permissions of the source Space are then extracted.  This is not a single object, but rather a collection of objects.

We iterate through each of the permission objects.  Each object is a collection of attributes.  We need to determine if the permissions object relates to a single user, or a group.  Every type of permission gets it’s own object.

Permissions objects associated with a group look like so:


The first attribute is the permission type.  The second is the permission ID. The third element is the group with which this permission is associated, and this is where the format of the permissions object differs