DEV Community

Vasiliy Zakharchenko
Vasiliy Zakharchenko

Posted on

Integrating External Services in Atlassian Forge — Without Losing the “Runs on Atlassian” Eligibility

When building Forge apps, sooner or later you’ll want to integrate with an external system — maybe for monitoring, data synchronization, or automation.
But the moment you call an external API using fetch(), your app loses the Runs on Atlassian badge.

This article shows how to design such an integration without any egress — meaning the Forge app never sends data outside Atlassian Cloud — and still communicates securely with an external backend.

The full demo project is available on GitHub:
Forge Health Monitor

The Architecture

The solution is based on two key capabilities that Atlassian Forge provides.

1. Safe navigation to external resources via router.navigate

Forge allows navigation to external pages using the @forge/bridge API:

import { router } from "@forge/bridge";

await router.navigate(registrationUrl);
Enter fullscreen mode Exit fullscreen mode

When this happens, Forge automatically shows a security confirmation dialog, warning the user that they’re leaving the Atlassian environment.
Importantly, this does not require any permissions in your manifest.yml.

The key idea is that during this redirect, the app passes non-sensitive contextual data to the external backend, such as:
cloudId — the unique tenant identifier (used to separate data by tenant on the external backend)
accountId — the Atlassian account of the user (may be shared across multiple tenants)
triggerUrl — a static web trigger endpoint unique to each tenant (unauthenticated by default, so custom authorization logic must be implemented)
callbackUrl — the Forge page to return

This pattern can also be extended to support OAuth authorization flows (Google, Microsoft, or Keycloak).

2. Static Web Triggers for inbound communication

Static Web Triggers are the second key mechanism.
They allow external services to send HTTP requests into Forge — and doing so does not violate the Runs on Atlassian requirement, because the call direction is inbound, not outbound.

Web triggers don’t provide built-in authentication, so you must implement it yourself.
In this example, authentication is done using Ed25519-signed requests — it’s a minimal working approach, though it could be further improved.

What Forge Health Monitor Application Does

Forge Health Monitor is a monitoring solution that allows you to track the health status of external services directly from your Jira instance. Here's what it does:

Core Functionality:

  • Monitors External Services - Continuously checks if your external APIs, websites, or services are running
  • Real-time Status Display - Shows current health status (ALIVE/DOWN) for all monitored services
  • User-friendly Interface - Simple Jira global page where you can view all your service statuses
  • Automatic Updates - Refreshes status every 30 seconds without manual intervention

Here’s how it works conceptually:

How to Run the Example

  1. Clone the repository

    git clone https://github.com/vzakharchenko/Forge-Health-Monitor
    cd Forge-Health-Monitor
    
  2. Install dependencies

    npm install
    
  3. Register the app in your Atlassian Developer Console

    forge register
    
  4. Start an ngrok tunnel on port 8080 — this will expose your custom backend:

    ngrok http 8080
    # Note the HTTPS URL (e.g., https://abc123.ngrok.app)
    


  5. Set the ngrok URL as a Forge environment variable

    forge variables set BACKEND_URL https://abc123.ngrok.app
    
  6. Deploy the Forge app

    forge deploy
    
  7. Install it into your Jira instance

    forge install
    
  8. Start the custom backend

    cd ./customBackend
    npm install
    npm run start
    


  9. The app and backend are now running — open your Forge app in Jira and test the flow!

Exploring the App

  1. Open your Jira instance and launch the Forge app
  2. Click “Add Service”
  3. Confirm navigation by clicking “Continue” in the system dialog
  4. Enter any publicly available health check URL that returns HTTP 200 (no authentication required). Only http and https URLs are accepted in this demo for simplicity.
  5. Click Continue, and you’ll return to the Forge app. You’ll see the new service in the list — the backend will now periodically (every 5 minutes) check the service’s availability.

Result

With this setup, we successfully integrated an external service without violating Runs on Atlassian.
All outbound requests are performed by the external backend, while Forge remains completely isolated and only receives signed updates through web triggers.

Top comments (0)