The Adaptavist Group LogoDocumentation

HTTP Endpoints

Use HTTP endpoints to define custom API endpoints for Jira. They enable you to integrate Jira with external systems by exposing custom logic over HTTP or by consuming external services from within Jira. You could use an HTTP endpoint to:

  • Provide an API that returns specific work item details Expose a custom HTTP endpoint that returns exactly the work item fields and data you need. Use this to power internal tools, dashboards, or integrations without giving direct access to Jira's full API.
  • Trigger Jira updates (such as transitions or field changes) based on external events Define an HTTP endpoint that, when called by an external system, performs actions in Jira, such as transitioning a work item, updating fields, or adding comments. Use this to keep Jira in sync with CI/CD pipelines, monitoring tools, or other business systems.
  • Aggregate and expose data from Jira and other systems in a single response Create an HTTP endpoint that calls Jira and other external APIs, combines the results, and returns a unified response. Use this to provide a single, simplified data source for reporting, dashboards, or downstream integrations.

HTTP endpoints are exposed as URLs that external systems can call, or that you can invoke from your own scripts and automations. All endpoints are mounted at /api/** and support GET, POST, PUT, DELETE, and PATCH.

Request object

When an HTTP endpoint is called, your script receives an ApiRequest object as its first argument. This object contains everything you need to handle the request; the HTTP method, any path or query parameters, headers, and the request body.

import type { ApiRequest, ApiResponse } from "@scriptrunnerhq/types/api-endpoints";
FieldTypeDescription
urlstringThe request URL (after the /api prefix)
methodstringHTTP method: GET, POST, PUT, DELETE, PATCH
pathParamsRecord<string, string | undefined>Named parameters from the path pattern
queryParamsRecord<string, string[]>Query string parameters
headersRecord<string, string[]>Request headers
bodystring (optional)Request body (for POST, PUT, PATCH)
contextobject (optional)Forge context: cloudId, moduleKey, and userAccess flags

A common pattern is to destructure the fields you need at the top of your script:

const { method, pathParams, queryParams, body } = request;

Response object

Your script must return an ApiResponse object. This tells ScriptRunner what HTTP status code and body to send back to the caller.

interface ApiResponse {
  statusCode: number
  body: string
}
  • statusCode — a standard HTTP status code, such as 200 for success, 201 for created, 400 for a bad request, or 404 for not found. Use appropriate codes to make your endpoint behave like a well-formed API.
  • body — must always be a string. If you want to return a JSON object, serialise it first with JSON.stringify().

A minimal valid response looks as follows:

return {
  statusCode: 200,
  body: JSON.stringify({ message: "Success" }),
};
Note: Always return an ApiResponse from every code path in your script, including error cases. If your script throws an unhandled error, the endpoint will return a 500 response.

Path patterns

The path you enter when creating an endpoint defines the URL route it responds to. Paths can include named parameters and wildcards, which are automatically extracted and made available in pathParams inside your script.

There are two types of dynamic segments:

  • Named parameters ( :paramName) — match a single path segment and capture its value. For example, :issueKey in /issues/:issueKey/links captures the issue key from the URL.
  • Wildcards ( :paramName*) — match one or more path segments and capture them as a single string. For example, :path* in /search/:path* captures everything after /search/.
PatternMatchespathParams
/issues/:issueKey/links/issues/ISSUE-42/links{ issueKey: "ISSUE-42" }
/issues/:issueKey/links/:linkId/issues/ISSUE-42/links/123{ issueKey: "ISSUE-42", linkId: "123" }
/projects/:projectKey/issues/projects/PROJ/issues{ projectKey: "PROJ" }
/repos/:owner/:repo/issues/repos/atlassian/AUI/issues{ owner: "atlassian", repo: "AUI" }
/search/:path*/search/a/b/c{ path: "a/b/c" }

Output and logging

When you run a script, the output panel shows:

  • Anything logged with console.log(...)
  • The final value returned by your script with return

Use console.log(...) for messages, intermediate values, or debugging, and include a return statement for the main result you want to display.

Activity history

Saved HTTP endpoints keep activity history (under Output), so you can review when they were run, and what the output was, making it easier to audit and troubleshoot.

Calling an endpoint externally

Once your endpoint is published, any external system or tool can call it over HTTP. Calls are authenticated with an OAuth 2.0 access token, so before you can call your endpoint you need to create an OAuth 2.0 app in the Atlassian developer console, give it the right scopes, and exchange a user's consent for a token.

This section covers the parts specific to ScriptRunner. For the full OAuth flow, see the Atlassian documentation Access REST APIs exposed by a Forge app.

Finding your endpoint URL

Your endpoint's full URL is displayed in the editor, under the path field, with a copy button. Endpoint URLs follow one of these patterns:

https://<site-name>.atlassian.net/gateway/api/svc/jira/apps/<appId>_<envId>/api/<path>
https://api.atlassian.com/svc/jira/<cloudId>/apps/<appId>_<envId>/api/<path>

Both resolve to the same handler. We recommend you use whichever fits your integration.

Required scopes

Your OAuth 2.0 app needs these scopes. Which ones you need depends on how the calling system authenticates:

How your integration authenticatesRequired scopes
As a Jira user, with that user granting consent (OAuth 2.0 three-legged, or 3LO)invoke:user-script:custom and read:forge-app:jira
Any other methodinvoke:user-script:custom
Note: If the calling service is missing the invoke:user-script:custom scope, requests will be rejected with a 403 Forbidden response.

Authentication

HTTP endpoints use OAuth 2.0 bearer token authentication. Include your access token in the Authorization header of every request:

Authorization: Bearer <access_token>

To get an access token, send the user to an authorization URL containing your app's client ID and the scopes above. For example:

https://auth.atlassian.com/authorize
  ?audience=api.atlassian.com
  &client_id=<your_client_id>
  &scope=invoke%3Auser-script%3Acustom%20read%3Aforge-app%3Ajira
  &redirect_uri=<your_redirect_uri>
  &state=<your_state>
  &response_type=code
  &prompt=consent

Exchange the returned code for an access token, then call your endpoint with it:

curl --request GET \
  --url 'https://api.atlassian.com/svc/jira/<cloudId>/apps/<appId>_<envId>/api/<path>' \
  --header 'Authorization: Bearer <access_token>'

For the full flow, including exchanging the code for a token, see the Atlassian documentation Access REST APIs exposed by a Forge app.

Staying authenticated

Access tokens expire. To avoid sending your users through the consent screen every time one does, request a refresh token by adding offline_access to your scopes:

&scope=offline_access%20invoke%3Auser-script%3Acustom%20read%3Aforge-app%3Ajira
Note:offline_access on its own is not enough. You must also request read:forge-app:jira, or the authorization request fails. This applies even if your integration would not otherwise need that scope.

You can then exchange the refresh token for a new access token without further user interaction. See the Atlassian documentation Implementing refresh tokens.

Create an HTTP endpoint

Follow these steps to create a new HTTP endpoint:

  1. In Jira administration, select Marketplace apps.
  2. Under Apps, select ScriptRunner.
  3. Select HTTP endpoints.
  4. Select Create.
  5. Enter a Name and, optionally, a Description.
  6. Enter a Path for the endpoint.

    The path defines the URL route your endpoint will be accessible at, and supports named parameters and wildcards. For example, /issues/:issueKey/links captures the issue key as a path parameter. See Path patterns for the full syntax reference.

  7. Choose who you want the script to Run as.

    Select whether the HTTP endpoint runs as the current user, with ScriptRunner app permissions, or as a specific user. The default is the current user.

  8. Write your script.
    Tip: To help you write scripts, you can use the HTTP endpoint examples, use HAPI, or select Example scripts directly in the script editor.
  9. Optional: Select Test HTTP endpoint, then Run, to run your script and make sure it works as expected.
    • The test data is seeded from the path you entered, so url shows your route pattern and each :param is waiting for a value. Fill those in rather than pasting the endpoint's real URL.
    • If the script performs updates (for example, creates or edits work items), those changes are applied to your Jira instance.
    • Test in a non-production environment first.
    • Use the Output panel to review results and troubleshoot any errors.
  10. Select Publish.

Edit an HTTP endpoint

Use these steps to modify an existing HTTP endpoint:

  1. In Jira administration, select Marketplace apps.
  2. Under Apps, select ScriptRunner.
  3. Select HTTP endpoints.
  4. Find your HTTP endpoint in the list and select Edit.
  5. Modify the HTTP endpoint as needed.

    Your changes are saved automatically as a draft. The published version keeps serving requests until you publish again.

  6. Optional: Select Test HTTP endpoint, then Run, to run your script and make sure it works as expected.
    • If the script performs updates (for example, creates or edits work items), those changes are applied to your Jira instance.
    • Test in a non-production environment first.
    • Use the Output panel to review results and troubleshoot any errors.
  7. Select Publish.

Enable and disable an HTTP endpoint

To enable or disable your HTTP endpoint:

  1. In Jira administration, select Marketplace apps.
  2. Under Apps, select ScriptRunner.
  3. In ScriptRunner, select HTTP endpoints.
  4. Locate the HTTP endpoint you want to enable or disable.
  5. Open the ellipsis (…) menu for that HTTP endpoint and select Disable or Enable.

Delete an HTTP endpoint

Remove HTTP endpoints you no longer need to keep your list organized and reduce clutter. When you delete an HTTP endpoint, it's removed from your active HTTP endpoints list and will no longer be callable, but it isn't permanently removed. You can still access and restore it from ScriptRunner if needed.

To delete an HTTP endpoint:

  1. In Jira administration, select Marketplace apps.
  2. Under Apps, select ScriptRunner.
  3. Select HTTP endpoints.
  4. Find the HTTP endpoint you want to remove.
  5. Open the ellipsis (…) menu for that HTTP endpoint.
  6. Select Delete.
  7. When prompted, confirm that you want to delete the HTTP endpoint.
Note: Deleted HTTP endpoints can be restored, including their activity history.

Restore a deleted HTTP endpoint

You can restore deleted HTTP endpoints along with their activity history. To restore a deleted HTTP endpoint:

  1. In Jira administration, select Marketplace apps.
  2. Under Apps, select ScriptRunner.
  3. Select HTTP endpoints.
  4. Use the filter and select Deleted to view deleted HTTP endpoints.
  5. Find the HTTP endpoint you want to restore.
  6. Open the ellipsis (…) menu for that HTTP endpoint.
  7. Select Restore.
    The HTTP endpoint and its activity history will be available again in your active HTTP endpoints list.

Search documentation

Start typing to search the docs.