Skip to content

[BE] New GraphQL query to fetch list of all created personal access tokens

We need a GraphQL query to fetch a list of all created personal access tokens for a user, both broad-access and fine-grained.

UX Figma view the data will be for

Proposed query:

query {
  user(id: "gid://gitlab/User/1") {
    id
    personalAccessTokens(sort: "EXPIRATION_DESC") {
      nodes {
        id
        name
        revoked
        createdAt
        description
        scopes
        granularScopes
        lastUsedAt
        active
        expiresAt
        lastUsedIps
      }
    }
  }
}

Example response:

{
  "data": {
    "user": {
      "id": "gid://gitlab/User/1",
      "personalAccessTokens": {
        "nodes": [
          {
            "id": "gid://gitlab/PersonalAccessToken/1",
            "name": "Broad-access token",
            "revoked": false,
            "createdAt": "2025-10-14T12:34:56Z",
            "description": "Broad token description",
            "scopes": "[\"k8s_proxy\", \"ai_features\"]",
            "lastUsedAt": "2025-10-20T15:42:17Z",
            "active": true,
            "expiresAt": "2025-11-14",
            "lastUsedIps": ["127.0.0.1", "1.2.3.4"]
          },
          {
            "id": "gid://gitlab/PersonalAccessToken/2",
            "name": "Fine-grained token",
            "revoked": true,
            "createdAt": "2025-10-15T19:38:14Z",
            "description": "Fine token description",
            "scopes": "[{\"boundary\": \"gid://gitlab/Group/1\",\"permissions\": [\"GROUP_PERMISSION\"]},{\"boundary\": \"gid://gitlab/Project/2\",\"permissions\": [\"PROJECT_PERMISSION\"]},{\"boundary\": \"gid://gitlab/User/1\",\"permissions\": [\"USER_PERMISSION\"]},{\"boundary\": \"MEMBERSHIPS\",\"permissions\": [\"READ_MEMBER_ROLES\"]},{\"boundary\": \"STANDALONE\",\"permissions\": [\"READ_MEMBER_ROLES\"]}]",
            "lastUsedAt": "2025-10-16T12:48:56Z",
            "active": false,
            "expiresAt": "2025-11-16",
            "lastUsedIps": ["127.0.0.1", "2.3.4.5"]
          }
        ]
      }
    }
  }
}

Several notes:

  1. In the UI, personal access tokens are sorted and paged, so we need both the broad and fine-grained tokens back in the same query.

  2. scopes returns a JSON string because for broad tokens it's an array of strings, but for fine-grained it's an array of objects.

Edited by Hinam Mehra