My Forge app calls the Atlassian Admin API using a Bearer token (key generated on admin.atlassian.com). It works fine with curl but always returns 401 inside Forge.
admin.atlassian.com
curl
The same key works perfectly in curl:
Hi @safa sahli
This is a very common and well-documented Forge pitfall. The core issue is that Forge apps cannot use a plain Bearer token (API key) for the Atlassian Admin API — the Forge runtime has specific constraints on how external HTTP calls are authenticated.
Why curl works but Forge doesn't:
fetch()
admin.atlassian.com/admin/v1/orgs
asApp()
asUser()
The correct approach:
<span>forge variables set --encrypt ADMIN_API_KEY your-key-here</span>
<span>import { fetch } from '@forge/api'; </span><span>const response = await fetch('https://api.atlassian.com/admin/v1/orgs', { </span><span> headers: { </span><span> 'Authorization': `Bearer ${process.env.ADMIN_API_KEY}`, </span><span> 'Accept': 'application/json' </span><span> } </span><span>});</span>
external fetch
manifest.yml
api.atlassian.com
Hello @safa sahli
I wouldn't be so quick to blame the API key just yet! Since your curl test worked fine, we already know the key itself is valid and the endpoint is happy to accept it. The real mystery here is likely how Forge is handling the request behind the scenes.
Org-level Admin APIs are a bit of a special case because they don't always play well with the standard Forge auth flow. You’ll want to double-check that this request is running through a backend resolver and that you've explicitly whitelisted api.atlassian.com in your manifest's external fetch permissions. The most common "gotcha" here is trying to use the standard asUser() or asApp() helpers since this needs a Bearer token, you actually need to use a regular fetch and manually set your Authorization header yourself.
If you’ve already got all that configured and you’re still seeing that 401, you might be bumping into a specific platform limitation. In that case, your best bet is to move the conversation over to the Atlassian Developer Community or reach out to support directly so the team can take a closer look at what’s happening under the hood.
Just two small additions to Ajay's and Arkadiusz's great answers:
1. The endpoint is **api.atlassian.com/admin/v1/orgs**, notadmin.atlassian.com (which 301-redirects and can drop auth headersin some runtimes). Worth double-checking from your screenshot.
2. The manifest snippet that's required:
permissions:external:fetch:backend:- "api.atlassian.com"
Without this Forge silently blocks the outbound call and yousometimes get 401 instead of a clearer egress error, which ismisleading.
3. If both are right and you still see 401, check the token's scopeon admin.atlassian.com → the org admin scope is separate from theproduct-level Jira scopes. A token that works for /rest/api/3 callswon't work for /admin/v1.
Hope it helps.
Germán
It looks like you're new here. Sign in or register to get started.