Problem Statement
Our Forge app (NASA Standup) needs to trigger Jira Automation rules when a standup meeting completes. Currently, the only way to do this is by calling
https://api-private.atlassian.com/automation/webhooks/{webhook-id} using fetch(), which requires declaring external.fetch permissions.
The paradox:
- api-private.atlassian.com is Atlassian’s own infrastructure
- The data never leaves Atlassian’s ecosystem
- Yet this disqualifies the app from “Runs on Atlassian” eligibility because Forge treats it as “external egress”
Current Implementation
We POST to Jira Automation webhooks with this structure:
const webhookResponse = await fetch(webhookUrl, {
method: ‘POST’,
headers: {
‘Content-Type’: ‘application/json’,
‘X-Automation-Webhook-Token’: webhookSecret,
},
body: JSON.stringify({
issues: [‘PROJ-123’, ‘PROJ-456’],
data: {
participant: ‘atlassian-account-id’,
comments: { ‘PROJ-123’: ‘Comment text’ }
}
}),
});
Security measures we’ve implemented:
- URL is hardcoded to only allow https://api-private.atlassian.com/automation/webhooks/ prefix
- Users cannot configure webhooks to any other domain
- Webhook secrets are stored securely in Forge Storage
Use Case
Users configure automation rules that trigger Jira Automation workflows when a standup completes:
- Create summary issues with flagged items
- Update issue statuses based on standup comments
- Send notifications via Jira Automation’s integrations (Slack, Teams, etc.)
This is a valuable feature that connects our app with Atlassian’s first-party automation platform.
Proposed Solutions
Option 1: Exempt api-private.atlassian.com for Automation Webhooks
Allow external.fetch to api-private.atlassian.com/automation/webhooks/* without disqualifying apps from “Runs on Atlassian”, since:
- It’s Atlassian-owned infrastructure
- It’s for a first-party Atlassian feature
- Data stays within Atlassian’s ecosystem
Option 2: New Forge SDK Method
import { automation } from ‘@forge/api’;
await automation.triggerWebhook({
webhookId: ‘webhook-uuid’,
webhookSecret: ‘secret-token’,
payload: { issues: [‘PROJ-123’], data: { … } }
});
This would be similar to how requestJira() and requestConfluence() work - internal Atlassian API calls that don’t require external.fetch declarations.
References
- https://developer.atlassian.com/platform/marketplace/runs-on-atlassian/
- https://developer.atlassian.com/platform/forge/runs-on-atlassian-apps/
- https://developer.atlassian.com/platform/forge/runtime-egress-permissions/
- https://developer.atlassian.com/platform/forge/building-automations/
Additional Context
We understand from documentation that “Atlassian is currently not able to allow-list Atlassian domains for other types of egress because this can lead to cross-tenant access to
data.” However, Jira Automation webhooks are inherently tenant-scoped - users create webhooks within their own Jira instance, and the webhook ID/secret combination ensures
tenant isolation.
We’d be happy to provide more technical details or discuss alternative approaches.