Use the YouTrack JavaScript API
The @jetbrains/youtrack-scripting-api package is shared by workflow rules and supported backend app modules. Use the examples on this page to work with entities and collections exposed by this API. Most examples use a workflow rule context, but the entity operations are the same in other backend modules when the corresponding entity is available.
Where to Write Backend Scripts
Choose the development flow that matches the module you are building.
To create a workflow and add modules in YouTrack, use the web-based workflow editor. For a guided example, see JavaScript Workflow Quick Start Guide.
To write workflow packages in an IDE, install the scripting packages and upload the workflow to YouTrack. For setup instructions, see Using an External Code Editor.
To build HTTP handlers, custom MCP tools, or packages that combine backend and frontend modules, use the app development flow.
Accessing Properties, Custom Fields, and Issue Links
Follow these guidelines to access issue properties, values in custom fields, and issue links.
- Predefined Issue Fields
Predefined issue fields like
summary,description, andreporterare all properties of theissueentity.const summary = issue.summary; issue.summary = "Just a bug";- Custom Field Values
References to values in a custom field vary based on whether the field stores single or multiple values.
For fields that store single values, you can reference the value directly:
const state = issue.fields.State; if (state && issue.fields.is(ctx.State, ctx.State.Fixed)) { // Do stuff } issue.fields.State = ctx.State.Open;For fields that store multiple values, the values are stored as a set. The operations that are available for sets are described in more detail in the next section.
const versions = issue.fields["Fix versions"]; versions.forEach(function (v) { subtask.fields["Fix versions"].add(v); });
When you need to inspect the field definition itself, get the
ProjectCustomFieldfrom the project and read itstypeName. Multi-value custom field types use the[*]suffix, for exampleuser[*]orversion[*]. Single-value bundle, user, and group field types use[1]; scalar field types such asintegerorstringdo not use a cardinality suffix.const assigneeField = issue.project.findFieldByName('Assignee'); if (assigneeField && assigneeField.typeName.endsWith('[*]')) { // Assignee stores multiple users in this project. }This runtime property is different from the
multiproperty in rule requirements. Usemulti: truewhen a rule requires a field to store multiple values; usetypeNamewhen a rule needs to inspect an existing field.When you compare custom field values that are represented by Workflow API entities, use API helper methods instead of comparing display names or object references. The
issue.fields.is(ctx.Field, ctx.Field.Value)method checks the current value,issue.fields.was(ctx.Field, ctx.Field.Value)checks the previous value, andissue.fields.becomes(ctx.Field, ctx.Field.Value)returnstrueonly when the field changed in the current transaction and its new value matches the expected value.- Aliases
If you set the
aliasproperty for a custom field in therequirementsstatement, you can use this alias to access values for the field as well. For example, if the alias for the Fix versions field is set toFV:issue.fields.FV.forEach(function (v) { // Do stuff });- Issue Links
Issue link types are accessed by their inward or outward name. For example,
relates toorparent for. Issue links are always treated as a set.const parent = issue.links["subtask of"].first(); parent.links["parent for"].add(issue);
Note that custom fields and issue link types that contain spaces or other non-alphabetic characters must be set in quotation marks and brackets.
Working with Set Objects
There are several groups of operations you can do with multiple values (returned as Set<value type>):
Access them directly (
first(),last(),get(index)) or by iterator (entries(),values()).Traverse over all values in Set with
forEach(visitor).Look for values with
find(predicate)and check if a value is in Set withhas(value).Check size with
isEmpty(),isNotEmpty()andsizeproperty.Modify content with
add(element),delete(element)andclear().Get the current changes for a Set object with the
added,deletedandisChangedproperties.
For a detailed description of this object, see Set.
Calling Methods
Finding Specific Entities
There are two ways to find a specific entity, like an issue or a user, and use it in a workflow script:
Add it in the requirements and reference it in the context. Use this approach as often as you can, as it is the most reliable. If the specified entity is not found in your database, the script is not executed.
If the first option is not applicable for whatever reason, use the
findBy*andfind*By*methods from the workflow API:
Use findBy* methods to find a single occurrence of a specific entity:
Use find*By* methods to find child entities:
Finding Multiple Issues
Sometimes you might want to find a set of issues that match certain criteria and process them in the scope of a single rule. For example, you can compile a list of issues and send it as an email message. In these situations, the search API can help. Here's a simple example:
Debugging Workflow Scripts
To inspect values while a workflow rule runs, add logging statements to the script:
Workflow script messages are displayed in the Console pane of the workflow editor, not in the browser developer console. For YouTrack Server installations, these messages are also written to the workflow.log file.
For more information about the console, see Console Toolbar. For additional diagnostic guidance, see Troubleshooting Workflows.