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.
Before using this guide, understand how data security policy APIs work
POST /v2/orgs/{orgId}/policies
This endpoint is designed to create a draft data security policy. To publish policies, see Publish data security policies.
Recommended flow:
ORG draft for the rule if none exists.WORKSPACE, CONTAINER, or CLASSIFICATION draft.publishDraftPolicies.WORKSPACE, CLASSIFICATION, CONTAINER or ORG.publicLinks, page export, attachmentDownload, anonymousAccess, or appAccess, with effect set to block or allowORG-level policy for the rule must exist first.
appAccess policies:
subjectId: all_apps for overrides to the default policy, OR the app's ARI for specific apps.CONTAINER and ORG coverage levels are supported for appAccess rulesCONTAINER-level app access policy requires an existing ORG-level policy for the same subject.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 # App ARI is in format ari:cloud:ecosystem::connect-app/marketplace/{appKey}. # To grab the appKey, go to https://{site}.atlassian.net/wiki/marketplace/discover, choose the app, and get the appKey from the URL: https://{site}.atlassian.net/wiki/marketplace/discover/app/{appKey} 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.
| HTTP | Code / message | Cause | What to do |
|---|---|---|---|
| 400 | ADMIN-400-24 — The draft org-wide policy does not contain the rule being overridden | No org-wide policy (draft or published) exists for that rule | Create an ORG-level draft with that rule first (e.g. export with effect: allow) |
| 400 | ADMIN-400-24 — Redundant draft override rule found | A 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 |
| 400 | ADMIN-400-24 — Invalid policyCoverageLevel | Wrong value for metadata.policyCoverageLevel | Use 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 } }
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
To grab the workspace resourceAri,
1 2# Add workspaces (sites) as resources to a policy. ResourceAri is a string. Use site ARIs: ari:cloud:confluence::site/{cloudId}, ari:cloud:jira::site/{cloudId}, etc. # To grab the cloudId, go to https://{site}.atlassian.net/_edge/tenant_info 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 2204 No content
Sample Request for adding container
1 2# Add containers (Confluence spaces or Jira projects) as resources. The resourceAri has format confluence:{cloudId}:space/{spaceId} or jira:{cloudId}:project/{projectId} # To grab cloudId, go to https://{site}.atlassian.net/_edge/tenant_info # To grab spaceId in Confluence, go to https://{site}.atlassian.net/wiki/api/v2/spaces and select the id of the space you want to attach # To grab projectId in Jira, go to https://{site}.atlassian.net/rest/api/3/project and select the id of the project you want to attach 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 2204 No content
Sample Request for adding classification
1 2# Add classification level as a resource. resourceAri is a string (platform classification-tag). The resourceAri has format: ari:cloud:platform::classification-tag/{tagId} # To grab the tagId in Confluence: https://{site}.atlassian.net/wiki/api/v2/classification-levels # To grab the tagId in Jira: https://{site}.atlassian.net/rest/api/3/classification-levels 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 2204 No content
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" } }
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:
lastUpdatedBy, createdBy, hasHadCoverage, and systemTag properties.id property and remove all others.attributes object, exclude the id, ownerId, createdAt, updatedAt, and queryData.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" } } } }'
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 onaction: UPDATE or DELETEpolicyCoverageLevel: WORKSPACE, CLASSIFICATION, CONTAINER, or ORGUpdating 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 2curl --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.
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 2curl --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 2curl --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 2202 Accepted
Rate this page: