Developer
News and Updates
Get Support
Sign in
Get Support
Sign in
DOCUMENTATION
Cloud
Data Center
Resources
Sign in
Sign in
DOCUMENTATION
Cloud
Data Center
Resources
Sign in
Last updated Dec 15, 2025

Customer-managed egress and remotes (EAP)

Customer-managed egress and remotes are currently available through Forge's Early Access Program (EAP). EAP capabilities are experimental, unsupported, and subject to change without notice, and are not recommended for production use.

For more details, see Forge EAP, Preview, and GA.

Customer-managed egress and remotes are a way of defining egress in your app. They let customers and admins control which external services your app can talk to, and when those connections are enabled.

In other implementations, Forge apps must declare all possible egress destinations up front, which limits customer choice and can introduce unnecessary security risks.

Customer-managed egress enables apps to declare and manage their egress and remotes per installation, instead of listing every destination in the manifest. This approach improves trust for customers by giving them more visibility and control over data flows, and provides more flexible integration options.

When to use it

Consider using customer‑managed egress and remotes when:

  • Your app integrates with external systems where the exact domains or endpoints differ per customer.
  • You want admins to have the ability to enable or disable specific integrations without a new app deployment.
  • You need to expose a “bring your own endpoint” or “bring your own domain” experience in your app’s configuration UI.
  • You want to strengthen your app’s trust posture by giving admins clear visibility and explicit consent over where data can be sent.
  • Your app doesn’t know in advance which domains a customer will need, but can offer a “permitted list of domains” experience.
  • Your app integrates with external services hosted on customer‑specific or variable URLs.
  • Different customers need to point the same app to different analytics, logging, or backend endpoints.

Customer‑managed egress and remotes must not be used to request pre‑defined, required egress.

If your app always needs to talk to specific external domains that are fixed or pre‑set, you must declare those via static external permissions and remotes, rather than prompting admins to approve them immediately via customer‑managed egress.

If your app always talks to the same fixed set of external destinations, you can keep using static external permissions and remotes.

Key benefits

  • Per‑installation control: Admins can define and manage which external domains an app can communicate with in the Forge app and in the Atlassian Administration Connected Apps page.
  • Feature gating by consent: Apps can expose features that rely on external integrations only when customers explicitly enable and configure them.
  • Better trust posture: Admins get clear visibility and explicit consent over where data can be sent, which helps with internal security reviews and compliance.

How it works

Instead of declaring every external destination up front in manifest.yml, your app can:

  • Ask an admin to approve new egress destinations and remote endpoints at runtime.
  • Store those choices per installation.
  • Use the configured values when making outbound calls.

Relationship to runtime egress permissions

  • Runtime egress permissions are the enforcement layer that decides, at invocation time, whether a call to an external domain is allowed.
  • Customer‑managed egress and remotes are ways to manage that configuration per installation via the Forge bridge APIs, instead of only via static manifest entries.
  • Both use the same underlying egress types and content security model; customer‑managed egress simply gives admins more control over the allowed destinations.

Forge apps that use customer‑managed egress or customer‑managed remotes are not eligible for Runs on Atlassian. For more information, see Limitations and compatibility.

Egress vs remotes

  • Egress groups describe which external domains your app is allowed to talk to, and for which types of traffic (backend fetch, client fetch, images, styles, and so on). They are a customer‑managed layer on top of the existing permissions.external.* model.
  • Remotes describe a specific backend service (with a key, base URL, purpose, and optional authentication configuration), which Forge can call via Forge Remote or use as a fetch backend. Customer‑managed remotes let admins supply or override the remote’s endpoint URL per installation.

In practice, you will usually:

  • Use customer-managed egress groups when you want admins to manage a list of allowed domains for different resource types.
  • Use customer‑managed remotes when you want admins to configure a single backend endpoint (by key) that your app or Forge Remote calls.

Customer‑managed egress groups

The customer-managed egress data model is based on the idea of an egress group. A group may have one or more egress entries defined. Grouping makes it easier for an admin to understand what a particular egress is related to.

An example egress group looks like:

1
2
{
  "key": "egress-group",
  "description": "Access to example.com",
  "configured": [
    {
      "domain": "https://api.example.com",
      "type": ["FETCH_BACKEND_SIDE", "FETCH_CLIENT_SIDE"]
    },
    {
      "domain": "https://media.example.com",
      "type": ["IMAGES", "MEDIA"]
    },
    {
      "domain": "https://cdn.example.com",
      "type": ["FONTS", "SCRIPTS", "STYLES"]
    }
  ]
}

Field details

FieldTypeDescription
keystringA key for the egress group that is defined by the Forge app.
descriptionstringA user‑facing description for this egress group.
configured[].domainstringA URL or wildcard that will be used to fetch resources from.
configured[].typeEgressType[]

The type(s) of allowed egress. These map to the existing manifest egress types documented in Add content security and egress controls.

There is an enum EgressType for the accepted types exposed from the @forge/egress package if you wish to import this in your app. Otherwise the following string values are accepted:

  • 'FETCH_BACKEND_SIDE'
  • 'FETCH_CLIENT_SIDE'
  • 'FONTS'
  • 'FRAMES'
  • 'IMAGES'
  • 'MEDIA'
  • 'SCRIPTS'
  • 'STYLES'

Customer‑managed remotes

The data model for a customer-managed remote looks like:

1
2
{
  "key": "external-api",
  "configured": {
    "endpoint": "https://api.external.com"
  }
}

Field details

FieldTypeDescription
keystringMust correlate to a remote key defined in the manifest.
endpointstring (URL)The absolute URL for the remote as defined by the admin of your app (inside configured).

Set up customer‑managed egress and remotes

1. Update the manifest to enable customer‑managed egress and remotes

Updating the manifest is not part of EAP scope but will be released as part of Preview. When using this feature in EAP, skip this section and focus on interacting with the Forge Bridge APIs.

To use customer‑managed egress or remotes, enable the feature in your app manifest:

1
2
permissions:
  external:
    configurable:
      enabled: true

If this property is not set to true, any calls to the customer-managed egress and remotes APIs will fail. This property is required for egress and remotes, but a customer-managed remote requires one additional property to be set.

For customer-managed remotes

Customer-managed remotes are defined in the manifest similarly to existing remotes, but add a configurable object describing how admins can configure the endpoint URL.

Basic example:

1
2
remotes:
  - key: my-site-1
    configurable:
      name: "My site"
      description: "This will be used to make connections to My Site"
      supportedPatterns:
        - "*.example.com"

Key points:

  • key is still required; remotes are always keyed values.
  • baseUrl becomes optional when configurable is defined. If you omit baseUrl, the remote is purely customer‑configured.
  • The configurable object provides:
    • name: Used in the Atlassian Administration Connected Apps UI and in in‑app modals to explain what the remote is used for.
    • description: Additional context about what the remote is used for.
    • supportedPatterns: An array of patterns used to validate admin‑provided URLs. This accepts any string values, including a single * wildcard character. Validation for these will be performed in Admin Hub, but not in a Forge app. Validating this is the responsibility of the app.

For example, to provide a default baseUrl while still allowing customers to override it:

1
2
remotes:
  - key: my-site-1
    baseUrl: "https://default.example.com"
    configurable:
      name: "My site"
      description: "This will be used to make connections to My Site"
      supportedPatterns:
        - "*.example.com"
Interaction with data residency

Customer-managed remotes and data residency follow the same rules as other remotes. You can combine customer-managed remotes with region‑specific baseUrl values:

1
2
remotes:
  - key: my-site-1
    baseUrl:
      default: "https://example.com"
      US: "https://us.example.com"
      EU: "https://eu.example.com"
    configurable:
      name: "My site"
      description: "This will be used to make connections to My Site"
      supportedPatterns:
        - "*.example.com"

In Atlassian Administration, if an admin resets a remote to its default value:

  • If no baseUrl is set in the manifest, the remote becomes unset (endpoint becomes null).
  • If a baseUrl is set in the manifest, the remote reverts to the manifest baseUrl (or the region‑specific baseUrl if applicable).

See Data residency and Remotes manifest reference for full details.

2. Use the Forge bridge APIs

Once the manifest is configured, your app can interact with customer‑managed egress and remotes at runtime using the Forge bridge.

All customer-managed egress and remotes APIs:

  • Are exposed from the permissions module in @forge/bridge.
  • Require permissions.external.configurable.enabled: true in the manifest.
  • Only allow admins to set or delete configuration (they show an admin consent modal).
  • Can be used to read configuration from both app code and resolvers.

There are six async Forge bridge functions available in @forge/bridge:

  • permissions.egress.get
  • permissions.egress.set
  • permissions.egress.deleteDomain
  • permissions.egress.deleteGroup
  • permissions.remote.set
  • permissions.remote.get

For detailed arguments and TypeScript types, see Forge bridge APIs.

Example: Let admins add an egress group from your UI

The following shows how you might call permissions.egress.set from a Custom UI component:

1
2
import { permissions } from "@forge/bridge";

async function configureEgress() {
  await permissions.egress.set({
    groups: [
      {
        key: "example-egress",
        description: "Access to example.com",
        configured: [
          {
            domain: "https://api.example.com",
            type: ["FETCH_BACKEND_SIDE"],
          },
        ],
      },
    ],
  });
}

When this is called by an admin, they will see a confirmation modal describing the egress that will be added. If they approve, the group is saved and the Promise resolves. If they reject, the Promise rejects.

Forge bridge APIs

Once the manifest of an app has been configured correctly, the app can interact with customer‑managed egress and remotes using six async Forge functions in the permissions module in @forge/bridge. All of these calls will fail if permissions.external.configurable.enabled is not set to true. These APIs are part of the Early Access Program and are not recommended for production use.

permissions.egress.get

Use this to get previously configured egress for an installation. You can fetch specific groups or all groups.

Arguments

  • keys (optional): Array of group keys to fetch. If undefined, all configured egress groups are returned.
  • pageSize (optional): Number of egress groups to return in a single page.
  • nextPageToken (optional): Token to fetch the next page of values when using pagination.

Type

1
2
type EgressGetPayload = {
  keys?: string[];
  pageSize?: number;
  nextPageToken?: string;
};

permissions.egress.set

Use this to set customer-managed egress for an installation. You can set one or multiple egress groups (up to the maximum allowed).

Arguments

  • groups: Array of egress groups to set. Each group has:
    • key: Key for this egress group. Must be unique for this installation.
    • description: Human‑readable description shown to admins.
    • configured: Array of entries, each containing:
      • domain: URL or wildcard for the egress destination.
      • type: One or more egress types (see EgressType).

Type

1
2
export type EgressSetPayload = {
  groups: {
    key: string;
    description: string;
    configured: {
      domain: string;
      type: EgressType;
    }[];
  }[];
};

permissions.egress.deleteDomain

Use this to delete a single domain from a previously defined egress group. This is useful when you want to keep the group but remove one domain/type entry.

Arguments

  • key: Key of the egress group to delete a domain from.
  • domain: Domain to be deleted from the group.
  • type: Egress type to be deleted for that domain.

Type

1
2
export type EgressDeleteDomainPayload = {
  key: string;
  domain: string;
  type: EgressType;
};

permissions.egress.deleteGroup

Use this to delete an entire egress group and all of its defined domains.

Arguments

  • key: Key of the egress group to be deleted.

Type

1
2
export type EgressDeleteGroupPayload = {
  key: string;
};

permissions.remote.set

Use this to set or update the endpoint of a customer-managed remote.

Arguments

  • key: Key of the remote to update. Must match a key defined in the app manifest.
  • configured:
    • endpoint: Absolute URL for the remote, or null to reset it:
      • If a baseUrl is defined in the manifest, resetting to null will restore the manifest value.
      • If no baseUrl is defined, resetting to null will unset the endpoint.

Type

1
2
export type Remote = {
  key: string;
  configured: {
    endpoint: string | null;
  };
};

permissions.remote.get

Use this to get previously configured remotes for an installation. You can fetch specific remotes or all remotes.

Arguments

  • keys (optional): Array of remote keys to fetch. If undefined, all configured remotes are returned.
  • pageSize (optional): Number of remotes to return in a single page. If this is not specified, all configured remotes will be returned.
  • nextPageToken (optional): Token to fetch the next page of values when using pagination.

Type

1
2
type RemoteGetPayload = {
  keys?: string[];
  pageSize?: number;
  nextPageToken?: string;
};

The underlying TypeScript definitions for these functions are published as part of the Forge SDK (see @forge/bridge/out/permissions/types.d.ts and @forge/egress for EgressType).

Admin experience

Customer‑managed egress and remotes are designed to be understandable and controllable for admins. An admin’s primary experience is usually within the context of your app, but some functionality is also available in Connected Apps in Atlassian Administration.

In‑app experience

When a Forge app invokes the set operations for egress or remotes, an admin will see a modal asking them to confirm the addition or change. If the permissions.external.configurable.enabled is not true, this will be rejected.

  • The description, domains, and remotes specified when calling these functions are shown in the modal.
  • The modal is controlled by Atlassian and is used to obtain explicit consent for new egress or remote destinations.
  • If the admin approves, the configuration is saved and the async function resolves.
  • If the admin rejects, the async function rejects.

If egress has already been configured for a particular domain and that domain is reused for a different type, the modal is not shown again for the same domain.

Connected Apps in Atlassian Administration

When viewing a specific app after navigating to Connected Apps in Atlassian Administration, and selecting an app, the Data management tab provides:

  • The ability to view and set a customer-managed remote:
    • Admins can update the customer-managed endpoint URL.
    • Admins can reset the remote back to the value defined in the manifest (or unset it if no default exists).
  • The ability to view egress groups configured by your app, and delete individual domains or entire groups.

This gives admins a centralized place to review data flows across multiple apps in their organization.

API access and admin control

The customer-managed egress and remotes APIs are designed so that admins must be in control of any changes:

  • Setting egress or remotes, and deleting egress groups or domains, is only available via the Forge bridge functions and must be explicitly approved by an admin.
  • These operations cannot be performed on behalf of an admin via Forge User Impersonation.
  • Reading configuration (for example, to adjust your UI based on configured egress/remotes) can be done from resolvers.
  • Changes to egress configuration are also recorded in Atlassian Guard audit logs, giving admins centralized visibility into who modified what and when.

For detailed API behaviour and type definitions, see the Forge bridge permissions reference.

Limitations and considerations

  • Runs on Atlassian eligibility:
    • Any app that uses customer‑managed egress or customer‑managed remotes is not eligible for Runs on Atlassian.
  • Maximum configuration limits:
    • Limits for the maximum number of customer‑managed egress entries and remotes per installation may apply. To confirm
  • Connect remotes:
    • Connect remotes cannot be dynamically added using customer-managed remotes. Adding a configurable field to a Connect remote will be rejected.

Rate this page: