There is no working credential-free path from a Forge app to the Atlassian Assets REST API. The Assets API (api.atlassian.com/jsm/assets/workspace/``...) is unreachable via requestJira(), and declaring CMDB OAuth scopes in manifest.yml results in 401 Unauthorized on every call — including in scheduled trigger context where there is no user session. The only working approach is direct fetch() to api.atlassian.com with Basic auth (email + API token), which is not viable for a Forge marketplace app.
Environment
-
Forge runtime:
nodejs24.x -
App type: Custom field type, admin page, scheduled trigger, workflow post-function
-
Atlassian cloud site: JSM with Assets (formerly Insight)
-
Forge CLI: latest as of May 2025
What we tried and the exact outcome
Attempt 1: requestJira() with gateway path
import { requestJira, assumeTrustedRoute } from '@forge/api';
const resp = await requestJira(
assumeTrustedRoute(`/gateway/api/jsm/assets/workspace/${workspaceId}/v1/objectschema/list`)
);
Result: HTTP 404 — HTML Jira error page (“Oops, you’ve found a dead link”). The gateway path does not exist.
Attempt 2: requestJira() with correct relative path + CMDB scopes
Based on the Atlassian scopes documentation at
https://developer.atlassian.com/cloud/assets/assets-rest-api-guide/scopes-for-oauth-2-3LO-and-forge-apps/
we added these scopes to manifest.yml:
permissions:
scopes:
- read:cmdb-schema:jira
- read:cmdb-object:jira
- read:cmdb-attribute:jira
And called:
const resp = await requestJira(
assumeTrustedRoute(`/jsm/assets/workspace/${workspaceId}/v1/objectschema/list`)
);
After forge deploy + forge install --upgrade:
Result: HTTP 401 {"code":401,"message":"Unauthorized"} — on every Assets API call, across all invocation contexts:
-
Resolver functions (user context)
-
Scheduled trigger functions (app context, no user session)
-
Web trigger functions (app context, no user session)
Additionally, adding the CMDB scopes broke existing working endpoints — the servicedeskapi workspace lookup (/rest/servicedeskapi/assets/workspace) which previously returned 200 also started returning 401 after the scope upgrade. This indicates the scope upgrade created a pending-consent state that invalidated the entire app token.
Attempt 3: Old Insight REST API v1
requestJira(route`/rest/insight/1.0/objectschema/list`)
Result: HTTP 404 {"detail":"No endpoint GET /rest/insight/1.0/objectschema/list."} — confirmed removed from Atlassian Cloud.
What does work
Direct fetch() to api.atlassian.com with Basic auth (email + API token), with api.atlassian.com added to the manifest egress allowlist:
const resp = await fetch(
`https://api.atlassian.com/jsm/assets/workspace/${workspaceId}/v1/objectschema/list`,
{ headers: { Authorization: `Basic ${btoa(`${email}:${token}`)}` } }
);
This works but requires per-installation credentials, which is not viable for a marketplace app.
Root cause (our analysis)
The documentation page title is “Scopes for OAuth 2.0 (3LO) and Forge apps” but the CMDB scopes behave as 3LO-only in practice. They appear to require an interactive per-user OAuth consent flow. Forge’s installation-level scope grant (via forge install --upgrade) does not satisfy this requirement. Since Forge has no mechanism to initiate a 3LO consent flow from inside a Forge app, these scopes are effectively unusable from Forge today.
Impact
Any Forge app that needs to read or write Assets data (object schemas, object types, attributes, AQL queries) has no supported credential-free path. This blocks building a proper Forge marketplace app for Assets use cases without requiring customers to supply and store a service account email + API token — creating credential management burden and a poor installation experience.
What we’re asking for
One or more of the following:
-
Make
requestJira()route to the Assets API — add a gateway proxy so thatrequestJira(route\/jsm/assets/workspace/${id}/v1/…`)works from Forge, the same wayrequestJira(route`/rest/servicedeskapi/assets/workspace`)` works today for the workspace lookup. -
Make CMDB scopes work at the installation level — ensure that
read:cmdb-schema:jira,read:cmdb-object:jira,read:cmdb-attribute:jiradeclared inmanifest.ymlare granted to the app’s installation token (not just as user-level 3LO scopes), so thatrequestJira()orapi.asApp().requestJira()can call the Assets API without per-user consent. -
Document the actual state clearly — if there is a workaround or if the feature is on a roadmap, document it. The current docs page implies these scopes work for Forge apps, but they do not in practice.
References
-
Assets scopes docs:
https://developer.atlassian.com/cloud/assets/assets-rest-api-guide/scopes-for-oauth-2-3LO-and-forge-apps/ -
Forge
requestJiradocs:https://developer.atlassian.com/platform/forge/runtime-reference/product-fetch-api/ -
Community thread: “How to Access JSM Assets API from Forge Back-End Functions”
-
Community thread: “Is it possible to query Assets using requestJira?”