Forge {"code":401,"message":"Unauthorized; scope does not match"}

I have tested to create a Rovo agent using forge, the agent role is to fetch ccounts in JSM, and return the users haven’t loged in in last 180days, to help admin for users review, but it fails to fetch the API:

I get this error:

ERROR 2026-06-28T23:46:29.594Z ec49ff6a-940d-49f5-9de5-b8a248e152ba Error: {“code”:401,“message”:“Unauthorized; scope does not match”}
at Object.getGroupMembersFull (webpack://users-review/src/index.js:21:13)

I have tried both const res = await api.asUser() and const res = await api.asApp() but always same error, could you help me to investigate the issue, for information I’m an ORG administrator.

Manifest.yml:

modules:
action:
- key: get-group-members-full
name: Get Full Group Membership
description: Retrieves all users in a group with their details
function: getGroupMembersFull
actionVerb: GET
inputs:
groupId:
title: Group ID
type: string
description: Atlassian Admin Directory Group ID
rovo:agent:
- key: users-review-agent
name: Users Review
description: Reviews group membership and inactive users
prompt: >
You help administrators review Atlassian group membership.
Ask for a Group ID if not provided.
Use get-group-members-full action and show all returned users.
conversationStarters:
- Show group members
- Find inactive users
actions:
- get-group-members-full
function:
- key: getGroupMembersFull
handler: index.getGroupMembersFull
app:
id: ari:cloud:ecosystem::app/1dfefea2-e33d-48c7-af0d-0d73816e08fa
runtime:
name: nodejs24.x
memoryMB: 256
architecture: arm64
permissions:
scopes:
- read:jira-user
- read:group:jira
external:
fetch:
backend:
- api.atlassian.com

Index.js

import api, { route } from '@forge/api';
const GROUP_ID = the_id_of_the_group;
export async function getGroupMembersFull() {
let users = [];
// Always start with a SAFE route object
let nextUrl = route`/rest/api/2/group/member?groupId=${GROUP_ID}`;
while (nextUrl) {
// ALWAYS pass route object directly here
const res = await api.asApp().requestJira(nextUrl, {
headers: {
Accept: 'application/json'
}
});
if (!res.ok) {
throw new Error(await res.text());
}
const data = await res.json();
users.push(...(data.values || []));
// Pagination
if (data.isLast === false && data.nextPage) {
// Convert absolute URL → safe route again
const next = new URL(data.nextPage);
nextUrl = route`${next.pathname}${next.search}`;
} else {
nextUrl = null;
}
}
return {
groupId: GROUP_ID,
total: users.length,
users
};
}

can you help me resolve the permission issue and add the 180days review

thank you in advance for your support.

hi @FatimaAALLA , the API you are trying to use can’t be used in Forge. I am linking here the API docs for reference https://developer.atlassian.com/server/jira/platform/rest/v10006/api-group-group/#api-api-2-group-member-get

Forge and OAuth2 apps cannot access this REST resource.

For your usecase, you need to call other alternative API that can be called via Forge

Hi @ShobhitSharma - I think you have linked the Server/DC docs, which are not applicable.

The Cloud API is https://developer.atlassian.com/cloud/jira/platform/rest/v2/api-group-groups/#api-rest-api-2-group-member-get which is accessible to Forge apps.

@FatimaAALLA the issue appears to be because you have not requested the right OAuth scopes to call this API. Your manifest specifies read:jira-user and read:group:jira (I’m not sure that is a real scope). However, the documentation I linked says that manage:jira-configuration is required to call this API.

Keep in mind that when you make changes to the permissions required by your app, the installation upgrade mechanics apply, and you will have to run forge install --upgrade against your installation using the Forge CLI in order for the new permissions to apply.