API Reference#
Reference documentation for the globals and APIs available in Automan scripts.
Overview#
Automan scripts run in a secure sandboxed environment with access to specific globals for interacting with Jira. This page documents all available APIs.
Global Variables#
event#
The event object contains context data about what triggered the script execution.
Its structure varies depending on the execution context.
Workflow Post Function Context#
{
// Work item being transitioned
issue: {
id: string, // Work item ID (e.g., "10001")
key: string // Work item key (e.g., "PROJ-123")
},
// Transition details
transition: {
id: string,
name: string,
from: { id: string, name: string },
to: { id: string, name: string }
},
// Post function metadata
postFunction: {
id: string
},
// User who performed the transition
atlassianId: string // Atlassian account ID
}Automation Action Context#
{
// The evaluated smart value you configured
smart: string,
// Automation metadata
automationId: string,
"context": {
"cloudId": string,
"moduleKey": "automan-run-script",
"userAccess": {
"enabled": boolean,
"hasAccess": boolean
}
},
contextToken: string
}Event Trigger Context#
{
// Event type identifier
eventType: string, // e.g., "avi:jira:created:issue"
// User who caused the event
atlassianId: string,
// Event-specific data (varies by event type)
issue: { ... }, // For work item events
comment: { ... }, // For comment events
version: { ... }, // For version events
changelog: { ... } // For update events
}Scheduled Script (Cron) Context#
{
type: "cron",
cronExpression: string, // e.g., "0 9 * * *"
scheduledTime: string // ISO 8601 timestamp of scheduled execution
}Test Execution Context#
{
type: "test"
}console#
Standard console object for logging.
console.log(…args)#
Logs messages to the execution log.
console.log("Simple message");
console.log("Multiple", "arguments", 123);
console.log("Object:", { key: "value" });Note: Logs are captured and available in the Executions tab.
process.env#
Object containing environment variables configured in the Environment tab.
// Access a variable
const apiKey = process.env.API_KEY;
// Check existence
if (process.env.WEBHOOK_URL) {
// Variable exists
}
// Default value pattern
const timeout = process.env.TIMEOUT || "30000";See Environment Variables for more details.
Functions#
requestJira API#
The requestJira function makes authenticated requests to the Jira REST API.
Syntax#
const response = await requestJira(route, options, actAsUser);Parameters#
| Parameter | Type | Required | Description |
|---|---|---|---|
route |
Route | Yes | API route created with the route template tag |
options |
Object | No | Request options (method, headers, body) |
actAsUser |
String | No | Account ID to make the request as that user |
Response#
Returns a Response object with:
ok- Boolean indicating success (status 200-299)status- HTTP status codestatusText- HTTP status textheaders- Response headersjson()- Async method to parse JSON response body
Basic Usage#
// GET request (default)
const response = await requestJira(route`/rest/api/3/myself`);
const data = await response.json();
// POST request
const response = await requestJira(
route`/rest/api/3/issue`,
{
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
fields: {
project: { key: "PROJ" },
summary: "New issue",
issuetype: { name: "Task" }
}
})
}
);
// PUT request
await requestJira(
route`/rest/api/3/issue/${issueKey}`,
{
method: "PUT",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
fields: { summary: "Updated summary" }
})
}
);
// DELETE request
await requestJira(
route`/rest/api/3/issue/${issueKey}`,
{ method: "DELETE" }
);Acting as a User#
By default, requestJira makes requests as the app (system user). To make requests as a specific user, pass their Account ID as the third parameter:
// Make request as the current user (from event)
const userId = event.user?.accountId;
const response = await requestJira(
route`/rest/api/3/issue`,
{
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
fields: {
project: { key: "PROJ" },
summary: "Issue created by user",
issuetype: { name: "Task" }
}
})
},
userId // Act as this user
);When to use actAsUser:
- Creating issues - The reporter will be the specified user
- Adding comments - The comment author will be the specified user
- Respecting permissions - The request will only succeed if the user has permission
- Audit trail - Actions are logged as performed by the user
Important notes:
- The user must have the necessary permissions for the action
- If the user lacks permission, the request will fail with a 403 error
- The Account ID can be found in
event.user.accountIdfor event triggers
Example: Create Issue as User#
// Get the user who triggered the event
const triggerUserId = event.user?.accountId;
if (triggerUserId) {
// Create a subtask as the triggering user
const response = await requestJira(
route`/rest/api/3/issue`,
{
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
fields: {
project: { key: event.issue.fields.project.key },
parent: { key: event.issue.key },
summary: "Follow-up task",
issuetype: { name: "Sub-task" }
}
})
},
triggerUserId
);
if (response.ok) {
const newIssue = await response.json();
console.log(`Created ${newIssue.key} as user ${triggerUserId}`);
}
} else {
console.log("No user context - creating as app");
// Fallback to app context (no third parameter)
}Error Handling#
Always check the response status:
const response = await requestJira(route`/rest/api/3/issue/${issueKey}`);
if (!response.ok) {
const error = await response.json();
console.log(`Error ${response.status}: ${response.statusText}`);
console.log("Details:", JSON.stringify(error));
return;
}
const issue = await response.json();route#
Template tag function for building Jira API routes with proper encoding.
Usage#
// Basic usage
route`/rest/api/3/issue/${issueKey}`
// With multiple parameters
route`/rest/api/3/issue/${issueKey}/comment/${commentId}`
// Query parameters should be appended separately
const jql = "project = PROJ";
route`/rest/api/3/search/jql?jql=${encodeURIComponent(jql)}`Why Use route?#
The route tag ensures:
- Proper URL encoding of parameters
- Correct route format for Jira API
- Security against injection attacks
Always use route instead of string concatenation:
// Correct
const response = await requestJira(route`/rest/api/3/issue/${issueKey}`);
// WRONG - Don't do this
const response = await requestJira(`/rest/api/3/issue/${issueKey}`);URLSearchParams#
Standard URLSearchParams class for building query strings.
const params = new URLSearchParams();
params.append("jql", "project = PROJ");
params.append("maxResults", "50");
params.append("fields", "summary,status");
const queryString = params.toString();
// "jql=project+%3D+PROJ&maxResults=50&fields=summary%2Cstatus"
// Or initialize with object
const params2 = new URLSearchParams({
jql: "project = PROJ",
maxResults: "50"
});
const queryParams = new URLSearchParams({
...(filterFields ? { fields: fieldsToDisplay } : {}),
});
route`/rest/api/3/issue/${issueKey}?${queryParams}`;Common Jira API Patterns#
Get Current User#
const response = await requestJira(route`/rest/api/3/myself`);
const user = await response.json();
console.log(user.displayName, user.emailAddress);Get Work Item Details#
const response = await requestJira(route`/rest/api/3/issue/${issueKey}`);
const issue = await response.json();
console.log("Key:", issue.key);
console.log("Summary:", issue.fields.summary);
console.log("Status:", issue.fields.status.name);
console.log("Assignee:", issue.fields.assignee?.displayName);Update Work Item Fields#
await requestJira(
route`/rest/api/3/issue/${event.issue.key}`,
{
method: "PUT",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
fields: {
summary: "Updated Summary",
description: {
type: "doc",
version: 1,
content: [{
type: "paragraph",
content: [{ type: "text", text: "New description" }]
}]
},
labels: ["label1", "label2"],
customfield_10001: "Custom value"
}
})
}
);Add Comment#
await requestJira(
route`/rest/api/3/issue/${issueKey}/comment`,
{
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
body: {
type: "doc",
version: 1,
content: [{
type: "paragraph",
content: [{ type: "text", text: "Your comment here" }]
}]
}
})
}
);Search Work Items (JQL)#
const jql = 'project = "PROJ" AND status = "In Progress"';
const response = await requestJira(
route`/rest/api/3/search/jql?jql=${encodeURIComponent(jql)}&maxResults=50`
);
const result = await response.json();
console.log(`Found ${result.total} work items`);
for (const issue of result.issues) {
console.log(issue.key, issue.fields.summary);
}Assign Work Item#
await requestJira(
route`/rest/api/3/issue/${issueKey}`,
{
method: "PUT",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
fields: {
assignee: { accountId: "5a0000000000000000000001" }
}
})
}
);Create Work Item#
const response = await requestJira(
route`/rest/api/3/issue`,
{
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
fields: {
project: { key: "PROJ" },
summary: "New Work Item Summary",
issuetype: { name: "Task" },
description: {
type: "doc",
version: 1,
content: [{
type: "paragraph",
content: [{ type: "text", text: "Description text" }]
}]
}
}
})
}
);
const newIssue = await response.json();
console.log("Created:", newIssue.key);Transition Work Item#
// First, get available transitions
const transResponse = await requestJira(
route`/rest/api/3/issue/${issueKey}/transitions`
);
const transitions = await transResponse.json();
// Find the transition you want
const targetTransition = transitions.transitions.find(t => t.name === "Done");
// Execute the transition
await requestJira(
route`/rest/api/3/issue/${issueKey}/transitions`,
{
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
transition: { id: targetTransition.id }
})
}
);Error Handling#
HTTP Errors#
const response = await requestJira(route`/rest/api/3/issue/${issueKey}`);
if (!response.ok) {
console.log("HTTP Error:", response.status, response.statusText);
const errorBody = await response.json();
console.log("Error details:", errorBody);
return;
}
const issue = await response.json();Try/Catch#
try {
const response = await requestJira(route`/rest/api/3/issue/${issueKey}`);
const issue = await response.json();
// Process work item...
} catch (error) {
console.log("Error:", error.message);
}Limitations#
Execution Time#
Scripts have a maximum execution time of 20 seconds. If a script exceeds this limit, it will be automatically terminated and return an error:
Script execution timed out after 20 secondsTips to avoid timeouts:
- Minimize the number of API calls
- Use JQL to filter data server-side rather than fetching all data and filtering in script
- For bulk operations, consider using Scheduled Scripts with pagination
- Avoid infinite loops and recursive operations without proper exit conditions
Example: Efficient pagination
// Process work items in batches to avoid timeout
const maxResults = 50;
let startAt = 0;
let hasMore = true;
while (hasMore && startAt < 200) { // Limit total to avoid timeout
const response = await requestJira(
route`/rest/api/3/search/jql?jql=${encodeURIComponent(jql)}&startAt=${startAt}&maxResults=${maxResults}`
);
const result = await response.json();
for (const issue of result.issues) {
// Process each work item
}
startAt += maxResults;
hasMore = result.issues.length === maxResults;
}API Rate Limits#
Be mindful of Jira API rate limits when making multiple requests.
No External HTTP#
Direct HTTP requests to external URLs are not supported. Use Jira API or store integration data in Jira.
No File System#
Scripts cannot access the file system.
No Imports#
External modules cannot be imported. Use the provided globals only.
Jira REST API Documentation#
For complete Jira REST API documentation, see:
Related Topics#
- Script Definitions - Creating and managing scripts
- Environment Variables - Storing configuration
- Workflow Post Functions - Workflow integration
- Automation Actions - Automation integration