Link Jira Issues Together
A ready-to-use Salesforce Flow action that creates a link between two Jira issues — for example ABC-1 blocks ABC-2 or ABC-5 relates to ABC-7 — with full support for bulk processing, asynchronous execution, optional comments, and error logging.
Table of contents:
- What this action does
- Typical use cases
- Adding the action to a Flow
- Action input fields
- Link direction explained
- Variable mode (dynamic values)
- Synchronous vs Asynchronous
- Errors and where to find them
- FAQ
What this action does
Link Jira Issues Together is an Apex Invocable Action (peeklogic_jc.LinkJiraIssuesTogetherAutomation) that you can drop into any Salesforce Flow — Record-Triggered, Screen, Scheduled, or Autolaunched. It creates a Jira issue link of type Blocks / Relates / Cloners / Duplicates / Causes / … between two existing Jira issues identified by their keys, with an optional comment.
Under the hood it performs a POST to the Jira REST endpoint /rest/api/2/issueLink using the named credential configured in Jira Connector Pro. Both Jira Cloud and Jira Server / Data Center are supported.
Typical use cases
- When a Salesforce Case is created, link its Jira issue to the parent Epic.
- When marking a Case as a duplicate, mark the corresponding Jira issue as “is duplicated by” the original.
- When a Bug record is closed by another Bug, create a “blocks / is blocked” by relationship between the two Jira issues.
- From a Screen Flow, let an end user pick two Jira keys and connect them with a chosen relationship type, optionally adding a justification comment.
- Bulk-link many issues at once — for example after a mass import — the action chains itself asynchronously and respects Salesforce governor limits.
Adding the action to a Flow
- Open Setup → Flows and create a new Flow or open an existing one.
- Drag an Action element onto the canvas.
- In the search box type Peeklogic Link Jira Issues Together and select it.
- The custom property editor (CPE) opens — fill in the fields described in Section 4.
- Save and activate the flow.
Action input fields
| Field | Required | Description |
| Source Issue Key | Yes | Key of the issue that performs the action. Read it as “<Source> <link verb> <Target>”. For ABC-1 blocks ABC-2, Source is ABC-1. Accepts a literal string or a Flow variable. |
| Target Issue Key | Yes | Key of the issue that receives the action. For ABC-1 blocks ABC-2, Target is ABC-2. |
| Link Type | Yes | The relationship type from Jira’s live list (Blocks / Relates / Cloners / Duplicates / Causes / …). The CPE loads the list from Jira at edit time so custom link types appear automatically. In variable mode you pass the Jira link type id as a string (for example 10003). |
| Link Direction | No (default outward) | Either outward or inward. In list mode this is set automatically when you pick the verb (e.g. “blocks” vs “is blocked by”). See Section 6. |
| Comment | No | Optional comment posted to Jira together with the link. HTML is accepted and automatically converted to Jira wiki markup before being sent. |
| Record Id | No | Id of the Salesforce record the Flow is running on. In a record-triggered Flow this field is auto-populated with $Record.Id and locked. It is stored on Sync_Error__c.Name so that any error log links back to the originating record via the Parent record formula. |
| Execute Asynchronously | No (default OFF) | Toggle. ON = the action enqueues a LinkJiraIssuesTogetherQueueable job (recommended for bulk and for record-triggered Run Immediately paths). OFF = the callout runs inline in the current transaction. See Section 8. |
Link direction explained
In Jira every link type has two names — an outward name and an inward name. For example the Blocks link type displays:
- → outward — blocks (Source blocks Target)
- ← inward — is blocked by (Source is blocked by Target)
In the Jira API both names share the same numeric id; the direction is encoded by which issue key goes into the outwardIssue field and which goes into the inwardIssue field of the request payload.
How we handle this for you: the CPE expands the raw list of Jira link types into ~15 directional options — exactly like Jira’s native UI. When you pick, say, is blocked by, the action swaps Source and Target automatically before calling Jira, so the resulting link reads correctly from the Source issue’s point of view. Administrators never have to think about inward / outward field placement.
Symmetric link types (for example Relates, where outward and inward names are identical) are collapsed into a single option marked ↔ symmetric — swapping makes no difference for them.
| Glyph | Direction | Example verb | What ends up in Jira |
| → | outward | blocks, causes, clones, duplicates | Source issue shows the outward verb pointing at Target. |
| ← | inward | is blocked by, is caused by, is cloned by, is duplicated by | Source issue shows the inward verb; the action swaps the keys for you. |
| ↔ | symmetric | relates to | Order is not meaningful — both issues display the same verb. |
Variable mode (dynamic values)
Each of the fields — Source / Target / Link Type / Direction / Comment / Record Id — can be switched into variable mode, where the value is taken from a Flow variable, constant, formula, or text template instead of being typed in literally.
Click the ⇆ icon next to the field to switch. The field turns into a resource picker grouped by type (Variables / Constants / Formulas / Text Templates), matching the standard Flow Builder experience.
| Field | Data type | What to pass |
| Source / Target Issue Key | String | A Jira key such as ABC-123. |
| Link Type | String | The Jira link-type id as a string (for example 10003). You can read the id from list mode in the same CPE. |
| Link Direction | String | outward or inward (case-insensitive). Any other value, or blank, falls back to outward. |
| Comment | String | HTML or plain text. |
| Record Id | String | A 15- or 18-character Salesforce Id (typically $Record.Id). |
| Execute Asynchronously | Boolean | Accepts only static Boolean values (true/false). |
Synchronous vs Asynchronous
| Mode | When to use | Behavior |
| Synchronous (toggle OFF — default) | Screen Flows, Autolaunched Flows, or Scheduled paths where no DML has been performed yet in the transaction. | The Jira callout runs immediately inside the current transaction. Fast, but subject to the per-transaction callout limit when run in bulk. |
| Asynchronous (toggle ON) | Bulk operations (more than one link at a time), Record-Triggered Flow on the Run Immediately path, or any scenario where DML has already happened in the transaction. | The request is enqueued in LinkJiraIssuesTogetherQueueable and executed one at a time with chaining. Not affected by per-transaction callout limits. |
Important: on the Run Immediately path of a Record-Triggered Flow (which runs synchronously after a DML), the synchronous mode will not work — Salesforce forbids HTTP callouts after DML in the same transaction. The transaction will fail with “You have uncommitted work pending”. In Sync_Error__c you will see Response_Status__c = Sync Mode Error (Uncommitted Work) with a hint pointing to the fix.
Solution: turn Execute Asynchronously ON, or move the action into an asynchronous / scheduled path of the Flow.
Errors and where to find them
Every failure is logged as a peeklogic_jc__Sync_Error__c record. The Type__c field takes one of these values:
- LinkJiraIssuesTogetherAutomation (Validation) — a required input is missing (Source, Target, or Link Type).
- LinkJiraIssuesTogetherAutomation (Sync) — the synchronous callout failed (HTTP error, non-201 response, or uncommitted-work pending).
- LinkJiraIssuesTogetherAutomation (Async) — the Queueable executed and Jira returned an error.
Key fields on the Sync_Error log:
| Field | Contents |
| Name | The Record Id passed into the action — turns into a clickable “Parent record” link on the Sync_Error detail page. |
| Response_Status__c | One of Validation Error, Sync Mode Error, Sync Mode Error (Uncommitted Work), or Async Mode Error. |
| Response_Body__c | JSON of the form { “errors”: { “<key>”: “<message>” } }, mirroring Jira’s own error format. |
| Request_Body__c | Snapshot of the input parameters (Source / Target / linkTypeId / direction / async flag) — used for diagnostics and replay. |
| Stack_Trace__c | Apex stack trace for sync and async failures. |
Tip: create a list view on Sync_Error__c filtered by Type__c contains “LinkJiraIssuesTogetherAutomation” for quick day-to-day monitoring.
FAQ
- Can I pass a Jira_Issue__c record id instead of a Jira key?
- Not in the current release. The action works exclusively with Jira keys (such as ABC-1) for clarity. Resolving by record id can be added later as an additive enhancement if there is demand.
- What happens if I pass a non-existent issue key?
- Jira returns 404; the failure is logged to Sync_Error__c with status Async Mode Error (or Sync Mode Error if async is OFF). Other records in the same bulk call continue to process normally.
- What happens if the connector is disabled?
- The action silently exits without making any callouts and without writing an error record. This is the standard behavior shared with every other invocable in Jira Connector Pro.
- Is there a limit on the number of links per call?
- No fixed limit. In asynchronous mode the Queueable processes one request per execute() and chains the rest, so per-transaction governor limits are not hit regardless of input size.
- What if I add a comment together with an inward link?
- Jira’s API quirk: a bundled comment in an issueLink payload is always attached to the issue placed in the inwardIssue field of the request — which, in inward mode, is the Target rather than the Source. That is rarely what the administrator means.
- To preserve the intent (“the comment belongs to the Source issue”), the action automatically splits the work into two calls when direction is inward and a comment is provided: first it creates the link without the comment, then it adds the comment in a separate REST call to the Source issue. The administrator does not need to do anything special.
- Can the same Flow link more than two issues?
- Yes — call the action once per pair. Each call creates exactly one link. In a Loop element with the asynchronous toggle ON, all calls are enqueued and chained.
- Does the action de-duplicate existing links?
- No — Jira itself rejects duplicates with a 400 response. The action surfaces that response as a Sync_Error so administrators can see it, but it does not silently swallow the case.