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
Runtimes
Web triggers
Async events
Dynamic Modules (Preview)
Customer-managed egress and remotes (Preview)
License API
Atlassian app REST APIs
Fetch APIs
LLMs API (Preview)
Last updated Mar 3, 2025

Dynamic Modules API (Preview)

Dynamic Modules is now available as a Forge preview feature.

Preview features are deemed stable; however, they remain under active development and may be subject to shorter deprecation windows. Preview features are suitable for early adopters in production environments.

We release preview features so partners and developers can study, test, and integrate them prior to General Availability (GA). For more information, see Forge release phases: EAP, Preview, and GA.

Dynamic modules registered during EAP must be re-registered for Preview.

You can manage Dynamic Modules through its REST API. This API checks every request for OAuth authorisation to determine if it has permissions to access the target installation.

No OAuth 2.0 scopes are required.

Remote compatibility

You can configure a remote backend to call the Dynamic Module REST API. See Calling Atlassian app APIs from a remote.

Remote backends can only use asApp calls for dynamic module operations; asUser calls are not allowed. This means your remote backend will only be able to call the Dynamic Modules API as a generic bot user.

requestAtlassian

The Forge SDK code examples on this page use the requestAtlassian module, which is available from the @forge/api package. This package module uses the app's credentials, determined by the scopes defined in the app's manifest.

Register a dynamic module

Send a POST request to /forge/installation/v2/dynamic/module to register a dynamic module for the current app installation. The module key is generated server-side as a UUID v4 and returned in the response.

Request

PropertyTypeRequired?Description
typestringYesThe dynamic module being created (for example, use trigger to specify the Trigger module)
datamapYesThe dynamic module's structure, but in JSON format. Dynamic modules currently available in Preview are:

Jira

Confluence

Jira Service Management

Code examples

1
2
import { asApp } from '@forge/api';
const payload = {
  type: "trigger",
  data: {
    events: [
      "avi:jira:updated:issue"
    ],
    "endpoint": "some-endpoint"
  }
}
const response = await asApp().requestAtlassian(`/forge/installation/v2/dynamic/module/`, {
  headers: {
    'Content-Type': 'application/json'
  },
  method: 'POST',
  body: JSON.stringify(payload),
});
const body = await response.text(); 
console.log(`Response: ${response.status} ${body}`);

Responses

201: OK

The dynamic module was successfully registered on the installation.

4XX Error codes

The request does not have permissions to access the target installation.

Example
1
2
{
  "message": "Authorization failed"
}

500: Internal Server Error

The Dynamic Module service encountered an unexpected problem.

1
2
{
  "message": "An internal error occurred"
}

Update a registered module

Send a PUT request to /forge/installation/v2/dynamic/module/<key> to update a dynamic module registered on the installation (identified by the module's key in the URL path).

Request

PropertyTypeRequired?Description
key (path)stringYesThe unique key of the target dynamic module on the installation. Provided in the URL path; the path key is authoritative.
dynamicModuleRequestmapYesPayload that defines the updated dynamic module

The dynamicModuleRequest body has the following properties:

PropertyTypeRequired?Description
typestringYesThe dynamic module being created (for example, use trigger to specify the Trigger module)
datamapYesThe dynamic module's structure, but in JSON format (the payloads in the Code examples use the Trigger module).

Code examples

1
2
import { asApp } from '@forge/api';
const key = "<SERVER-GENERATED-UUID>";
const payload = {
  type: "trigger",
  data: {
    events: [
      "avi:jira:updated:issue"
    ],
    "endpoint": "some-endpoint"
  }
}
const response = await asApp().requestAtlassian(`/forge/installation/v2/dynamic/module/${key}`, {
  headers: {
    'Content-Type': 'application/json'
  },
  method: 'PUT',
  body: JSON.stringify(payload)
});
const body = await response.text(); 
console.log(`Response: ${response.status} ${body}`);

Responses

200: OK

The taget dynamic module was successfully updated. The response will contain the payload of the updated dynamic module.

Example
1
2
{
  "key": "<SERVER-GENERATED-UUID>",
  "type": "trigger",
  "data": {
    "key": "<SERVER-GENERATED-UUID>",
    "events": [
      "avi:jira:updated:issue"
    ],
    "endpoint": "some-endpoint"
  }
}

4XX Error codes

The specified key does not match the key specified in the dynamicModuleRequest map.

Example
1
2
{
  "message": "Key cannot be modified during update"
}

500: Internal Server Error

The Dynamic Module service encountered an unexpected problem.

1
2
{
  "message": "An internal error occurred"
}

List registered modules

Send a GET request to /forge/installation/v2/dynamic/module/ to retrieve a paginated list of dynamic modules currently registered on the app installation.

If a registered dynamic module shares the same key as a static module declared in your app's manifest.yml, the static module takes precedence and the dynamic module will be omitted from the response.

To make the dynamic module discoverable, update your manifest.yml to remove or rename the clashing key, then redeploy your app.

Request

PropertyTypeRequired?Description
nextPageTokenstringNoPagination cursor for fetching subsequent dynamic modules. This field is only present in a response if a strict subset of dynamic modules was previously fetched from this installation.
limitintegerNoMaximum number of dynamic modules to return

Code examples

1
2
import { asApp } from '@forge/api';
const params = new URLSearchParams({
  limit: '10',
  nextPageToken: '<PAGINATION-TOKEN>'
}).toString();
const response = await asApp().requestAtlassian(`/forge/installation/v2/dynamic/module/?${params}`, {
  headers: {
    'Content-Type': 'application/json'
  },
  method: 'GET'
});
const body = await response.text(); 
console.log(`Response: ${response.status} ${body}`);

Responses

200: OK

Dynamic modules were successfully fetched.

Example
1
2
[
  {
    "key": "a-dynamic-module",
    "type": "trigger",
    "data": {
      "key": "a-dynamic-module",
      "function": "jira-updated-issue-handler",
      "events": [
        "avi:jira:updated:issue"
      ]
    }
  },
  {
  "key": "another-dynamic-module",
  "type": "trigger",
  "data": {
    "filter": {
      "expression": "event.issue.fields?.issuetype.name == 'Bug'",
      "onError": "RECEIVE_AND_LOG"
    },
    "key": "another-dynamic-module",
    "endpoint": "some-endpoint",
    "events": [
      "avi:jira:updated:issue"
    ]
    }
  }
]

4XX Error codes

The request does not have permissions to access the target installation.

Example
1
2
{
  "message": "Authorization failed"
}

500: Internal Server Error

The Dynamic Module service encountered an unexpected problem.

1
2
{
  "message": "An internal error occurred"
}

Retrieve a registered module

Send a GET request to /forge/installation/v2/dynamic/module/<key> to retrieve a registered dynamic module on the installation (identified by the module's key).

Request

PropertyTypeRequired?Description
keystringYesThe unique key of the target dynamic module on the installation

Code examples

1
2
import { asApp } from '@forge/api';
const key = '<YOUR-MODULE-KEY>';
const response = await asApp().requestAtlassian(`/forge/installation/v2/dynamic/module/${key}`, {
  headers: {
    'Content-Type': 'application/json'
  },
  method: 'GET'
});
const body = await response.text(); 
console.log(`Response: ${response.status} ${body}`);

Responses

200: OK

The specified dynamic module was successfully fetched.

Example
1
2
{
  "key": "a-dynamic-module",
  "type": "trigger",
  "data": {
    "key": "a-dynamic-module",
    "events": [
      "avi:confluence:viewed:page"
    ],
    "function": "confluence-viewed-handler"
  }
}

4XX Error codes

The request does not have permissions to access the target installation.

Example
1
2
{
  "message": "Authorization failed"
}

500: Internal Server Error

The Dynamic Module service encountered an unexpected problem.

1
2
{
  "message": "An internal error occurred"
}

Delete a registered module

Send a DELETE request to /forge/installation/v2/dynamic/module/<key> to delete a registered dynamic module on the installation
(identified by the module's key).

Request

PropertyTypeRequired?Description
keystringYesThe unique key of the target dynamic module on the installation

Code examples

1
2
import { asApp } from '@forge/api';
const moduleKey = '<YOUR-MODULE-KEY>';
const response = await asApp().requestAtlassian(`/forge/installation/v2/dynamic/module/${moduleKey}`, {
  headers: {
    'Content-Type': 'application/json'
  },
  method: 'DELETE'
});
console.log(`Response: ${response.status}`);

Responses

204: No Content

No content will be returned if the target dynamic module was successfully deleted.

4XX Error codes

The request does not have permissions to access the target installation.

Example
1
2
{
  "message": "Authorization failed"
}

500: Internal Server Error

The Dynamic Module service encountered an unexpected problem.

1
2
{
  "message": "An internal error occurred"
}

Rate this page: