Developer
News and Updates
Get Support
Sign in
Get Support
Sign in
DOCUMENTATION
Cloud
Data Center
Resources
Sign in
Sign in
DOCUMENTATION
Cloud
Data Center
Resources
Sign in
Last updated Feb 26, 2026

Data security policy cookbook

Overview

Data security policies allow you to govern how users, apps, and people outside your organization interact with content such as Confluence pages and Jira issues. You can create policies in the Atlassian Administration or via the API. It's important to note that not all rules are available for all policy coverage types.

This guide will help you create a policy and apply it to your organization.

Explore Admin Control APIs

Before using this guide, understand how data security policy APIs work

Recommended flow: 1) Create an ORG draft for the rule if none exists. 2) Create a WORKSPACE, CONTAINER, or CLASSIFICATION draft. 3) Add resources. 4) Get policy and resources to validate. 5) Publish via publishDraftPolicies.

Create a new Data Security Policy

POST /v2/orgs/{orgId}/policies

A data security policy can include a coverage rule for publicLinks, page export, attachmentDownload, anonymousAccess, or appAccess. Set effect to block or allow for the corresponding effect. Each policy should contain exactly one rule.

When creating any type of policy, you must ensure that a policy with ORG coverage for the specified rule exists first (draft or published). The API uses policyCoverageLevel: "ORG" (not ORG_WIDE). If it does not already exist, create an org-wide draft before proceeding with WORKSPACE, CONTAINER, or CLASSIFICATION drafts—otherwise you get 400 with "The draft org-wide policy does not contain the rule being overridden" (ADMIN-400-24). Only one draft override per rule per coverage level is allowed per org; a second draft for the same rule and level returns "Redundant draft override rule found". To re-run create flows, delete existing data-security drafts first (e.g. DELETE /v1/orgs/{orgId}/policies/{policyId} for each draft) or create the org-wide policy first.

For appAccess policies, the subject of the policy should be defined. If the policy is meant to be an override to the default policy, then subjectId should be all_apps. Otherwise, it should be the ARI of the app that it applies to. A CONTAINER level app access policy should only be created if an ORG level policy exists for the same subject.

This endpoint is designed to create a draft policy without setting a coverage initially. To publish policies, see Publish data security policies. The addition of coverage will be addressed in subsequent steps. Please note that a specific policy can only be associated with one type of coverage: WORKSPACE, CLASSIFICATION, CONTAINER or ORG. For appAccess rules, only CONTAINER and ORG coverage levels are supported.

Sample Request: create org-wide draft first (Required when no org-wide policy exists for the rule). Multiple rules can be added to an org-wide policy.

1
2
# Create an org-wide draft so workspace/container/classification drafts can override this rule
curl --request POST \
  --url 'https://api.atlassian.com/admin/control/v2/orgs/{orgId}/policies' \
  --header 'Authorization: Bearer <access_token>' \
  --header 'Content-Type: application/json' \
  --header 'Accept: application/json' \
  --data '{
    "data": {
      "type": "policy",
      "attributes": {
        "type": "data-security",
        "name": "Org-wide default export",
        "status": "draft",
        "metadata": { "policyCoverageLevel": "ORG" },
        "rule": { "export": { "effect": "allow" } }
      }
    }
  }'
  
# Create an org-wide draft with all rules so workspace/container/classification drafts can override this rule
curl --request POST \
  --url https://api.atlassian.com/admin/control/v2/orgs/{orgId}/policies \
  --header 'Authorization: Bearer <access_token>' \
  --header 'Content-Type: application/json' \
  --data '{
	"data": {
		"type": "policy",
		"attributes": {
			"type": "data-security",
			"name": "Org Wide policy with all rules",
			"subject": {
				"subjectType": "marketplaceApp",
				"subjectId": "all_apps"
			},
			"rule": {
				"export": {
					"effect": "allow"
				},
				"publicLinks": {
					"effect": "allow"
				},
				"anonymousAccess": {
					"effect": "allow"
				},
				"appAccess": {
					"effect": "allow"
				}
			},
			"status": "draft",
			"metadata": {
				"policyCoverageLevel": "ORG",
				"description": "Org wide with all rules allow"
			}
		}
	}
}'

Sample Requests: create workspace/container/classification draft

1
2
# This will create a draft data security policy without any resources
curl --request POST \ 
  --url 'https://api.atlassian.com/admin/control/v2/orgs/{orgId}/policies' \
  --header 'Authorization: Bearer <access_token>' \
  --header 'Accept: application/json' \
  --header 'Content-Type: application/json' \
  --data '{ "data": {
        "type": "policy",
        "attributes": {
            "type": "data-security",
            "name": "test policy",
            "status": "draft",
            "metadata": {
                "policyCoverageLevel": "CLASSIFICATION",
                "description": "Some description"
            }, 
            "rule": {
                "export": {
                    "effect": "block"
                }
            }
        }
    }
}'

# App access policy with a subject
curl --request POST \ 
  --url 'https://api.atlassian.com/admin/control/v2/orgs/{orgId}/policies' \
  --header 'Authorization: Bearer <access_token>' \
  --header 'Accept: application/json' \
  --header 'Content-Type: application/json' \
  --data '{ "data": {
        "type": "policy",
        "attributes": {
            "type": "data-security",
            "name": "test policy",
            "status": "draft",
            "metadata": {
                "policyCoverageLevel": "CONTAINER",
                "description": "Some description"
            }, 
            "rule": {
                "appAccess": {
                    "effect": "block"
                }
            },
            "subject": {
              "subjectId": "all_apps",
              "subjectType": "marketplaceApp"
            }
        }
    }
}'

Sample Requests: create draft appAccess container coverage policy flow

1
2
# Create org-wide coverage level draft appAccess policy with subject all_apps if it doesn't already exist
curl --request POST \
  --url 'https://api.atlassian.com/admin/control/v2/orgs/{orgId}/policies' \
  --header 'Authorization: Bearer <access_token>' \
  --header 'Accept: application/json' \
  --header 'Content-Type: application/json' \
  --data '{
    "data": {
      "type": "policy",
      "attributes": {
        "type": "data-security",
        "name": "test policy",
        "status": "draft",
        "metadata": {
          "policyCoverageLevel": "ORG",
          "description": "Some description"
        },
        "rule": {
          "appAccess": {
            "effect": "allow"
          }
        },
        "subject": {
          "subjectId": "all_apps",
          "subjectType": "marketplaceApp"
        }
      }
    }
  }'
  
# Create org-wide coverage level draft appAccess policy with specified app in the subject
curl --request POST \
  --url 'https://api.atlassian.com/admin/control/v2/orgs/{orgId}/policies' \
  --header 'Authorization: Bearer <access_token>' \
  --header 'Accept: application/json' \
  --header 'Content-Type: application/json' \
  --data '{
    "data": {
      "type": "policy",
      "attributes": {
        "type": "data-security",
        "name": "test policy",
        "status": "draft",
        "metadata": {
          "policyCoverageLevel": "ORG",
          "description": "Some description"
        },
        "rule": {
          "appAccess": {
            "effect": "allow"
          }
        },
        "subject": {
          "subjectId": "ari:cloud:ecosystem::connect-app/specific-app",
          "subjectType": "marketplaceApp"
        }
      }
    }
  }'

# Create container coverage level draft appAccess policy with specified app in the subject
curl --request POST \
  --url 'https://api.atlassian.com/admin/control/v2/orgs/{orgId}/policies' \
  --header 'Authorization: Bearer <access_token>' \
  --header 'Accept: application/json' \
  --header 'Content-Type: application/json' \
  --data '{
    "data": {
      "type": "policy",
      "attributes": {
        "type": "data-security",
        "name": "test policy",
        "status": "draft",
        "metadata": {
          "policyCoverageLevel": "CONTAINER",
          "description": "Some description"
        },
        "rule": {
          "appAccess": {
            "effect": "block"
          }
        },
        "subject": {
          "subjectId": "ari:cloud:ecosystem::connect-app/specific-app",
          "subjectType": "marketplaceApp"
        }
      }
    }
  }'

Sample Response

The response to this call will include a policyId; save it for the subsequent steps.

Common errors when creating policies

HTTPCode / messageCauseWhat to do
400ADMIN-400-24 — The draft org-wide policy does not contain the rule being overriddenNo org-wide policy (draft or published) exists for that ruleCreate an ORG-level draft with that rule first (e.g. export with effect: allow)
400ADMIN-400-24 — Redundant draft override rule foundA draft already exists for the same rule and coverage level (e.g. workspace + export)Delete the existing draft via DELETE /v1/orgs/{orgId}/policies/{policyId} or use a different rule/coverage
400ADMIN-400-24 — Invalid policyCoverageLevelWrong value for metadata.policyCoverageLevelUse one of: UNASSIGNED, ORG, WORKSPACE, CONTAINER, CLASSIFICATION, DC_WORKSPACE (use ORG for org-wide, not ORG_WIDE)
1
2
{
    "data": {
        "type": "policy",
        "id": "358d916a-aed3-474a-9ae0-17def3bad866",
        "attributes": {
            "id": "358d916a-aed3-474a-9ae0-17def3bad866",
            "ownerId": "706c6425-3967-42b3-a070-53ffba3102b3",
            "type": "data-security",
            "name": "test policy",
            "rule": {
                "export": {
                    "effect": "block"
                }
            },
            "status": "draft",
            "metadata": {
                "lastUpdatedBy": "ari:cloud:identity::user/8044ac9ff568615bdc7ea094",
                "createdBy": "ari:cloud:identity::user/8044ac9ff568615bdc7ea094",
                "hasHadCoverage": true,
                "systemTag": null,
                "policyCoverageLevel": "CLASSIFICATION",
                "description": "Some description"
            },
            "createdAt": "2024-04-06T02:46:56.707Z", 
            "updatedAt": "2024-04-06T02:46:56.707Z", 
            "queryData": null
        }, 
        "links": null,
        "relations": null,
        "message": null
    }
}

Add resources to the policy

POST /v2/orgs/{orgId}/policies/{policyId}/resources

Show me how to create classification levels within an org

After you create a policy, add resources to it via /resources endpoint.

Anything marked with the classification level you choose will immediately follow the policy's rules.

This API can ADD or REMOVE one or more resources to/from policies. If you need to remove all associated resources, deleting the policy with the DELETE data security policy API and starting again might be faster.

Sample Request for adding workspace

1
2
# Add workspaces (sites) as resources to a policy. Use site ARIs: confluence::site/{siteId}, jira-software::site/{siteId}, etc.
curl --request POST \
  --url 'https://api.atlassian.com/admin/control/v2/orgs/{orgId}/policies/{policyId}/resources' \
  --header 'Authorization: Bearer <access_token>' \
  --header 'Content-Type: application/json' \
  --header 'Accept: application/json' \
  --data '[
    { 
      "operation": "ADD", 
      "resourceAri": "ari:cloud:confluence::site/4518289c-2159-48b9-a4f6-ae8f629aa2a2" 
    }, 
    { 
      "operation": "ADD", 
      "resourceAri": "ari:cloud:jira::site/1988289c-2159-48b9-a4f6-ae8f629aa2a2" 
    }
]'

Sample Response

1
2
204
No content

Sample Request for adding container

1
2
# Add containers (Confluence spaces or Jira projects) as resources. resourceAri is a string.
curl --request POST \
  --url 'https://api.atlassian.com/admin/control/v2/orgs/{orgId}/policies/{policyId}/resources' \
  --header 'Authorization: Bearer <access_token>' \
  --header 'Content-Type: application/json' \
  --header 'Accept: application/json' \
  --data '[
    {
      "operation": "ADD",
      "resourceAri": "ari:cloud:confluence:ee3c3183-3d6e-4077-8053-676d62c40929:space/10005"
    },
    {
      "operation": "ADD",
      "resourceAri": "ari:cloud:jira:ee3c3183-3d6e-4077-8053-676d62c40929:project/10004"
    }
]'

Sample Response

1
2
204
No content

Sample Request for adding classification

1
2
# Add classification level as a resource. resourceAri is a string (platform classification-tag).
curl --request POST \
  --url 'https://api.atlassian.com/admin/control/v2/orgs/{orgId}/policies/{policyId}/resources' \
  --header 'Authorization: Bearer <access_token>' \
  --header 'Content-Type: application/json' \
  --header 'Accept: application/json' \
  --data '[
    {
      "operation": "ADD",
      "resourceAri": "ari:cloud:platform::classification-tag/28a6d272-0d95-4a81-baea-a0660f490afc"
    }
  ]'

Sample Response

1
2
204
No content

Validate the attached resources

GET /v2/orgs/{orgId}/policies/{policyId} and GET /v2/orgs/{orgId}/policies/{policyId}/resources

Before publishing, fetch the policy and its resources to confirm configuration. The resource applicationStatus should transition to applied when ready.

Sample Request

1
2
# Retrieve policy details
curl --request GET \
  --url 'https://api.atlassian.com/admin/control/v2/orgs/{orgId}/policies/{policyId}' \
  --header 'Authorization: Bearer <access_token>' \
  --header 'Accept: application/json'

Sample Response - workspace

1
2
{
  "data": [
    {
      "type": "resource",
      "id": "d653c974-8d83-4ea9-b6b7-b49e18c69391",
      "attributes": {
        "parentResourceId": "ari:cloud:platform::org/c74e07d8-ddc2-4583-a8bc-5d5405a3907a",
        "resourceId": "ari:cloud:confluence::confluence::site/4518289c-2159-48b9-a4f6-ae8f629aa2a2",
        "applicationStatus": "applied",
        "createdAt": "2024-06-23T03:55:39.128Z",
        "updatedAt": "2024-06-23T03:55:38.900Z"
      }
    },
    {
      "type": "resource",
      "id": "d653c974-8d83-4ea9-b6b7-b49e18c69391",
      "attributes": {
        "parentResourceId": "ari:cloud:platform::org/c74e07d8-ddc2-4583-a8bc-5d5405a3907a",
        "resourceId": "ari:cloud:jira::confluence::site/1988289c-2159-48b9-a4f6-ae8f629aa2a2",
        "applicationStatus": "applied",
        "createdAt": "2024-06-23T03:55:39.128Z",
        "updatedAt": "2024-06-23T03:55:38.900Z"
      }
    }
  ],
  "meta": {
    "page_size": 2,
    "next": null,
    "prev": null

  },
  "links": {
    "self": "string",
    "prev": "loremipsum-prev",
    "next": "loremipsum-next"
  }
}

Sample Response - Container

1
2
{
  "data": [
    {
      "type": "resource",
      "id": "d653c974-8d83-4ea9-b6b7-b49e18c69391",
      "attributes": {
        "parentResourceId": "ari:cloud:confluence::site/ee3c3183-3d6e-4077-8053-676d62c40929",
        "resourceId": "ari:cloud:confluence::site/ee3c3183-3d6e-4077-8053-676d62c40929/space/10005",
        "resourceName": "Test project",
        "resourceKey": "~62cf0218ec233f24684a01a1",
        "resourceStatus": "active",
        "resourceLogoUrls": {
          "default": "/images/logo/default-space-logo-256.png"
        }
        "links": null,
        "message": null
      }
    },
    {
      "type": "resource",
      "id": "d653c974-8d83-4ea9-b6b7-b49e18c69391",
      "attributes": {
        "parentResourceId": "ari:cloud:jira::site/ee3c3183-3d6e-4077-8053-676d62c40929",
        "resourceId": "ari:cloud:jira::site/ee3c3183-3d6e-4077-8053-676d62c40929/project/10003",
        "resourceName": "Test project",
        "resourceKey": "~62cf0218ec233f24684a01a1",
        "self": "https://beacon-staging.jira-dev.com/admin/private/rest/api/2/project/10000",
        "projectType": "service_desk",
        "resourceStatus": "archived",
        "resourceLogoUrls": {
          "16x16": "https://beacon-staging.jira-dev.com/admin/private/rest/api/2/universal_avatar/view/type/project/avatar/10404?size=xsmall",
          "24x24": "https://beacon-staging.jira-dev.com/admin/private/rest/api/2/universal_avatar/view/type/project/avatar/10404?size=small",
          "32x32": "https://beacon-staging.jira-dev.com/admin/private/rest/api/2/universal_avatar/view/type/project/avatar/10404?size=medium",
          "48x48": "https://beacon-staging.jira-dev.com/admin/private/rest/api/2/universal_avatar/view/type/project/avatar/10404"
        },
        "links": null,
        "message": null
      }
    }
  ],
  "meta": {
    "page_size": 2,
    "next": null,
    "prev": null
  },
  "links": {
    "self": "string",
    "prev": "loremipsum-prev",
    "next": "loremipsum-next"
  }
}

Sample Response - Classification

1
2
{
  "data": [
    {
      "type": "resource",
      "id": "d653c974-8d83-4ea9-b6b7-b49e18c69391",
      "attributes": {
        "parentResourceId": "ari:cloud:platform::org/c74e07d8-ddc2-4583-a8bc-5d5405a3907a",
        "resourceId": "ari:cloud:platform::classification-tag/28a6d272-0d95-4a81-baea-a0660f490afc",
        "applicationStatus": "applied",
        "createdAt": "2024-06-23T03:55:39.128Z",
        "updatedAt": "2024-06-23T03:55:38.900Z"
      },
      "links": null,
      "message": null
    }
  ],
  "meta": {
    "page_size": 2,
    "next": null,
    "prev": null
  },
  "links": {
    "self": "string",
    "prev": "loremipsum-prev",
    "next": "loremipsum-next"
  }
}

Modify a policy

PUT /v2/orgs/{orgId}/policies/{policyId}

Before modifying the policy, fetch the details of the policy and review its configuration. It is crucial to modify the policy object only after retrieving its details.

Remove the auto-generated data listed below from the response:

  • From the metadata object, eliminate the lastUpdatedBy, createdBy, hasHadCoverage, and systemTag properties.
  • From each resource entry, retain only the id property and remove all others.
  • From the attributes object, exclude the id, ownerId, createdAt, updatedAt, and queryData.
  • From the data object, remove the id, links, relations, and message.

You can update name, description, and/or effect. You can only modify policies in a draft status. To modify published policies, see Publish data security policies.

Example: Update description property to a new value and resubmit a JSON object via PUT call.

Sample Request

1
2
# Update policy description
curl --request PUT \
  --url 'https://api.atlassian.com/admin/control/v2/orgs/{orgId}/policies/{policyId}' \
  --header 'Authorization: Bearer <access_token>' \
  --header 'Accept: application/json' \
  --header 'Content-Type: application/json' \
  --data '{"data": {
        "type": "policy",
        "attributes": {
            "type": "data-security",
            "name": "test policy",
            "rule": {
                "export": {
                    "effect": "block"
                }
            },
            "status": "draft",
            "metadata": {
                "policyCoverageLevel": "CLASSIFICATION",
                "description": "A new description"
            }
        }
    }
}'

Publish data security policies

POST /v2/orgs/{orgId}/policies/publishDraftPolicies

Publishing policies is done by a bulk request for a specific ruleName. This is the only way to create or modify published policies.

The policyOperations array should include operations that define the following:

  • policyId: id of the policy to be acted on
  • action: UPDATE or DELETE
  • policyCoverageLevel: WORKSPACE, CLASSIFICATION, CONTAINER, or ORG

Updating a draft policy via publishDraft will replace any equivalent published policy with the now-published draft policy.

For appAccess rules: include a policy operation for the default (all_apps) ORG policy, and if updating an app-specific policy, include that app's ORG level policy in policyOperations. For export, publicLinks, anonymousAccess, you typically only include the workspace/container/classification policy operations (no ORG required unless you are publishing an org-wide draft).

Sample Request

1
2
curl --request POST \
  --url 'https://api.atlassian.com/admin/control/v2/orgs/{orgId}/policies/publishDraftPolicies' \
  --header 'Authorization: Bearer <access_token>' \
  --header 'Accept: application/json' \
  --header 'Content-Type: application/json' \
  --data '{
	"type": "data-security",
	"ruleName": "appAccess",
	"policyOperations": [
		{
			"policyId": "6d338cb1-501a-4017-bafd-d1ddcbb9f0aa",
			"action": "UPDATE",
			"policyCoverageLevel": "ORG"
		},
		{
			"policyId": "0cb2bcd5-fcb7-4b09-b27d-0b901d5ece10",
			"action": "UPDATE",
			"policyCoverageLevel": "CONTAINER"
		},
		{
			"policyId": "e5012592-a520-4093-9351-76ac8a769a75",
			"action": "DELETE",
			"policyCoverageLevel": "CONTAINER"
		}
	]
}'

Sample Response

1
2
{
    "messages": [
        {
            "messageId": "b9045023-9f4a-4448-9f3f-04a987186de1",
            "ticket": {
                "id": "b9045023-9f4a-4448-9f3f-04a987186de1",
                "containerAri": "ari:cloud:platform::org/185b5ad5-3c85-45f2-abe4-91e7b4ecd5c8",
                "scope": "USER"
            }
        }
    ]
}

The messageId in the response can be used by support engineers in the event of an error.

Delete a data security policy

There are two ways to delete a data security policy. Note that the published default (all_apps) ORG level policy cannot be deleted.

Recommended: Use the publishDraft endpoint to delete the policy. On a policyOperation, set the action to DELETE and the policyId to the id of the published or draft policy that you want to delete.

1
2
curl --request POST \
  --url 'https://api.atlassian.com/admin/control/v2/orgs/{orgId}/policies/publishDraftPolicies' \
  --header 'Authorization: Bearer <access_token>' \
  --header 'Accept: application/json' \
  --header 'Content-Type: application/json' \
  --data '{
	"type": "data-security",
	"ruleName": "appAccess",
	"policyOperations": [
		{
			"policyId": "6d338cb1-501a-4017-bafd-d1ddcbb9f0aa",
			"action": "UPDATE",
			"policyCoverageLevel": "ORG"
		},
		{
			"policyId": "e5012592-a520-4093-9351-76ac8a769a75",
			"action": "DELETE",
			"policyCoverageLevel": "CONTAINER"
		}
	]
}'

Alternatively, you can use the delete endpoint to delete a specific policy.

DELETE /v1/orgs/{orgId}/policies/{policyId}

Sample Request

1
2
curl --request DELETE \
  --url 'https://api.atlassian.com/admin/control/v1/orgs/{orgId}/policies/{policyId}' \
  --header 'Authorization: Bearer <access_token>' \
  --header 'Accept: application/json'

Sample Response

1
2
202
Accepted

Rate this page: