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

Using the Projects GraphQL API

Overview

Refer to this page for further guidance on how to use the Projects GraphQL API.

Prerequisites

Your GraphQL request needs to be sent to this url: https://{subdomain}.atlassian.net/gateway/api/graphql.

Authentication

Authentication proves who you are. The Projects GraphQL API supports three ways to authenticate a request. Once authenticated, what you can access is determined by Authorization.

Scoped API token

Our GraphQL API supports Basic Authentication. Instead of a password, you use your scoped or classic API token along with your user email.

Create your API token

See the Manage API tokens for your Atlassian account page to create an API token.

Copy this API token to use in the next step.

cURL example with API tokens

You can construct and send basic auth headers. To do this you perform the following steps:

  1. Build a string of the form user@example.com:api_token_string
  2. BASE64 encode the string
  3. Supply an Authorization header with content Basic followed by a space, then the encoded string
  4. Send the request to https://{subdomain}.atlassian.net/gateway/api/graphql
  5. Sample request would be as follows:
1
2
curl -D- \
   -X POST \
   -H "Authorization: Basic BASE_64_ENCODED{EMAIL:TOKEN}" \
   -H "Content-Type: application/json" \
   --data-binary '{"query":"query WhoAmI {me{user{name}}}","operationName":"WhoAmI"}' \
   "https://{subdomain}.atlassian.net/gateway/api/graphql"

This should return a JSON response similar to the following:

1
2
{"data":{"me":{"user":{"name":"Jane Doe"}}},"extensions":{"gateway":{"request_id":"{requestId}","trace_id":"{traceId}","crossRegion":false,"edgeCrossRegion":false}}}%

OAuth 2.0 (2LO) — Service account access

Use this for server-to-server integrations that run without user interaction (for example, automated syncs or reporting pipelines). It uses the OAuth 2.0 client-credentials flow and also support scoped access tokens.

  1. Create a service account in Atlassian Administration.
  2. Generate an OAuth 2.0 credential (client ID / client secret) and select the required Projects scopes (see Authorization).
  3. Exchange the credential for an access token via grant_type=client_credentials against https://auth.atlassian.com/oauth/token.
  4. Pass the token as a Bearer header: Authorization: Bearer <ACCESS_TOKEN>.

Full guide: Create OAuth 2.0 credential for service accounts

Authorization

Authentication proves who you are; authorization determines what you can do. When you authenticate with OAuth (2LO or 3LO) or a scoped service-account credential, your access is constrained by the scopes granted to your token.

OAuth scopes for Projects

Request the scopes your integration needs when configuring your OAuth 2.0 (3LO) app or service-account credential.

ScopeGrants access to
read:project:projectsRead project core data and links
read:access:projectsRead project membership and access info
write:project:projectsCreate, edit, archive, and clone projects
write:update:projectsPost and manage project updates and comments
write:chat-integration:projectsConnect or disconnect Slack and MS Teams channels
delete:project:projectsDelete project content
manage:access:projectsManage project access and watchers

How scopes are enforced

  • Scopes are checked per operation. If your token is missing a required scope, the request is rejected with an authorization error.
  • Scopes define what your integration may do. The authenticated user's (or service account's) permissions determine which specific projects they can see or change.
  • Both the scope check and the permission check must pass for a request to succeed.

Note: For queries, a missing field-level scope returns null for that field with a matching entry in the errors array, while other authorized fields still resolve.

Making requests

GraphQL uses HTTP POST and application/json content type. This is a requirement of the GraphQL-over-HTTP specification.

The payload of the GraphQL request follows the GraphQL-over-HTTP specification. See this documentation for how to add variables and extensions to the payload.

Examples

Query a project with projects_byId

Let us assume you want to use projects_byId to query for the name and contributors of a project with id ari:cloud:townsquare:{siteId}:project/{projectUuid} .

Your GraphQL query would look like as follows:

1
2
query ProjectQuery {
  projects_byId(projectId:"ari:cloud:townsquare:{siteId}:project/{projectUuid}") {
    name
    contributors {
      edges {
        node {
          userContributor {
            id
            name
          }
          teamContributor {
            team {
              id
              displayName
              members {
                edges {
                  node {
                    member {
                      id
                      name
                    }
                  }
                }
              }
            }
          }
      	}
      }
    }
  }
}

From this, your cURL command would be as follows:

1
2
curl -X POST 'https://{subdomain}.atlassian.net/gateway/api/graphql' \
  --header 'Content-Type: application/json' \
  --header 'Authorization: Basic <YOUR_BASE_64_TOKEN_HERE>' \
  --data '{"query":"query ProjectQuery { projects_byId(projectId:\"ari:cloud:townsquare:{siteId}:project/{projectUuid}\") { name contributors { edges { node { userContributor { id name } teamContributor { team { id displayName members { edges { node { member { id name } } } } } } } } } } }"}'

Query projects with projects_byIds

Let us assume you want to use projects_ byIds to query for the name of the projects, its descriptions, due dates, updates and unresolved risks. The projects you want to query have ids of ari:cloud:townsquare:{siteId_1}:project/{projectUuid_1} and ari:cloud:townsquare:{siteId_2}:project/{projectUuid_2}.

Note that at the time of writing this example, theupdates field on a project was marked as experimental, and so we opted in by using the optIn directive @optIn(to: "Townsquare").

Your GraphQL query would look like as follows:

1
2
query ProjectsQuery {
  projects_byIds(
    projectIds: ["ari:cloud:townsquare:{siteId_1}:project/{projectUuid_1}", "ari:cloud:townsquare:{siteId_2}:project/{projectUuid_2}"]
  ) @optIn(to: "Townsquare") {
    name
    description {
      what
      why
    }
    dueDate {
      confidence
      dateRange {
        start
        end
      }
    }
    updates {
      edges {
        node {
          summary
        }
      }
    }
    risks (isResolved: false) {
      edges {
        node {
          summary
          description
        }
      }
    }
  }
}

From this, your cURL command would be as follows:

1
2
curl -X POST 'https://{subdomain}.atlassian.net/gateway/api/graphql' \
  --header 'Content-Type: application/json' \
  --header 'Authorization: Basic <YOUR_BASE_64_TOKEN_HERE>' \
  --data '{"query":"query ProjectsQuery { projects_byIds( projectIds: [\"ari:cloud:townsquare:{siteId_1}:project/{projectUuid_1}\", \"ari:cloud:townsquare:{siteId_2}:project/{projectUuid_2}\"] ) @optIn(to: \"Townsquare\") { name description { what why } dueDate { confidence dateRange { start end } } updates { edges { node { summary } } } risks (isResolved: false) { edges { node { summary description } } } } }"}'

Create a project with projects_create

Let us assume you want to use projects_create to create a project with the name "Project created from GraphQL" and a target date of the 31st of December 2026.

Your GraphQL mutation would look like as follows:

1
2
mutation CreateProjectMutation {
  projects_create (
    input: {
      containerId: "ari:cloud:townsquare::site/{siteId}"
    	name: "Project created from GraphQL"
      targetDate:{
        date: "2026-12-31"
        confidence:QUARTER
      }
    }
  ) {
    project {
      id
      name
    }
  }
}

From this, your cURL command would be as follows:

1
2
curl -X POST 'https://{subdomain}.atlassian.net/gateway/api/graphql' \
  --header 'Content-Type: application/json' \
  --header 'Authorization: Basic <YOUR_BASE_64_TOKEN_HERE>' \
  --data '{"query":"mutation CreateProjectMutation { projects_create ( input: { containerId: \"ari:cloud:townsquare::site/{siteId}\" name: \"Project created from GraphQL\" targetDate:{ date: \"2026-12-31\" confidence:QUARTER } } ) { project { id name } } }"}'

Create an update for a project with projects_createUpdate

Let us assume you want to use projects_createUpdate to create an update for a project with id ari:cloud:townsquare:{siteId}:project/{projectUuid}. From the response, you would like to know whether the operation succeeded and retrieve the id, url, creation date, summary, new target date, new target date confidence, and highlights of the project.

Your GraphQL mutation would look like as follows:

1
2
mutation CreateProjectUpdateMutation  {
  projects_createUpdate(
    input: {
      projectId: "ari:cloud:townsquare:{siteId}:project/{projectUuid}"
      summary: "{\"version\":1,\"type\":\"doc\",\"content\":[{\"type\":\"paragraph\",\"content\":[{\"type\":\"text\",\"text\":\"Description body for the update.\"}]}]}"
      status: "off_track"
      targetDate: {
        date: "2026-03-15",
        confidence: DAY
      }
      highlights: {
        summary:"Summary of the learning"
        description: "{\"version\":1,\"type\":\"doc\",\"content\":[{\"type\":\"paragraph\",\"content\":[{\"type\":\"text\",\"text\":\"The description of the learning.\"}]}]}"
        type: LEARNING
      }
    }
  ) {
    success
    errors {
      message
    }
    update {
      id
      url
      creationDate
      summary
      newTargetDate
      newTargetDateConfidence
      highlights {
        edges {
          node {
            summary
            description
          }
        }
      }
    }
  }
}

From this, your cURL command would be as follows:

1
2
curl -X POST 'https://{subdomain}.atlassian.net/gateway/api/graphql' \
  --header 'Content-Type: application/json' \
  --header 'Authorization: Basic <YOUR_BASE_64_TOKEN_HERE>' \
  --data '{"query":"mutation CreateProjectUpdateMutation { projects_createUpdate( input: { projectId: \"ari:cloud:townsquare:{siteId}:project/{projectUuid}\" summary: \"{\\\"version\\\":1,\\\"type\\\":\\\"doc\\\",\\\"content\\\":[{\\\"type\\\":\\\"paragraph\\\",\\\"content\\\":[{\\\"type\\\":\\\"text\\\",\\\"text\\\":\\\"Description body for the update.\\\"}]}]}\" status: \"off_track\" targetDate: { date: \"2026-03-15\", confidence: DAY } highlights: { summary:\"Summary of the learning\" description: \"{\\\"version\\\":1,\\\"type\\\":\\\"doc\\\",\\\"content\\\":[{\\\"type\\\":\\\"paragraph\\\",\\\"content\\\":[{\\\"type\\\":\\\"text\\\",\\\"text\\\":\\\"The description of the learning.\\\"}]}]}\" type: LEARNING } } ) { success errors { message } update { id url creationDate updateType summary newTargetDate newTargetDateConfidence highlights { edges { node { summary description } } } } } }"}'

An important thing to note here is the description of the highlights field needs to be in Atlassian Document Format.

Archive a project with projects_edit

Let us assume you want to use projects_edit to archive a project with id ari:cloud:townsquare:{siteId}:project/{projectUuid}. From the response, you would like the id, name, and archived status of the project.

Your GraphQL mutation would look like as follows:

1
2
mutation ArchiveProjectMutation {
  projects_edit(input: {
    id: "ari:cloud:townsquare:{siteId}:project/{projectUuid}"
    archived: true
  }) {
    project {
      id
      name
      isArchived
    }
  }
}

From this, your cURL command would be as follows:

1
2
curl -X POST 'https://{subdomain}.atlassian.net/gateway/api/graphql' \
  --header 'Content-Type: application/json' \
  --header 'Authorization: Basic <YOUR_BASE_64_TOKEN_HERE>' \
  --data '{"query":"mutation ArchiveProjectMutation { projects_edit(input: { id: \"ari:cloud:townsquare:{siteId}:project/{projectUuid}\" archived: false }) { project { id name isArchived } } }"}'

Rate this page: