Files
riposte-marketplace/integrations/jira/manifest.yaml
T
f3nris b9822f310d docs(jira): say what to type in each command field
Every input carried a description, and most of them restated the field name:
"Comment ID" for comment_id, "Board ID" for board_id, "JQL query string" for
query. That is a label, not help. An operator filling get_incidents for the
first time has no way to learn from it that the fetch appends its own
created >= watermark clause and an ORDER BY, that writing either breaks it,
that the watermark box is filled by the alert rule rather than by hand, or that
a run makes a single call and silently drops whatever exceeds max.

103 input fields rewritten to answer two questions instead: what goes in this
box, and where do I get it. Formats are shown by example rather than named —
2026-09-30 rather than "yyyy-mm-dd", soc,phishing rather than "comma-separated"
— and every field holding an id now names the command that returns it:
get_id_by_attribute for an assignee, board_list for a board, get_comments for
a comment, get_issue for an attachment, get_link_types for a link type and for
which issue belongs on which side of it.

Fields that replace rather than append say so, since labels and components
quietly drop whatever is left out.
2026-09-02 13:56:28 +02:00

368 lines
25 KiB
YAML

id: jira
name: Jira
version: 1.0.2
description: "Atlassian Jira (REST API, Cloud and On-Prem/Data Center) — issue lifecycle (create/read/edit/delete, transitions, assign), comments, web + issue links, attachments (upload/download/delete), field and user lookups, agile boards/sprints/epics, plus issue ingestion (get_incidents) with an OCSF mapper. Basic (email + API token) or Personal Access Token authentication. Stdlib-only, no extra Python dependencies."
changelog: "1.0.2 — Command field help rewritten: every input now says what to type, in what format, and which command finds the value, instead of restating the field name. get_incidents explains that the fetch adds its own created >= watermark clause and ORDER BY, that the watermark is filled by the alert rule, and that a run does not page. Assignee, board, sprint, comment and attachment fields name the command that returns their id. 1.0.1 — A personal access token silently outranked Basic credentials, so an unusable value left in pat turned every call into an opaque 401. Basic authentication now wins whenever username and api_key are both set, pat serves the rest, and a 401/403 names the method it used and whether the other was configured and ignored. Three configurations that cannot work are refused with the reason instead of being sent to Jira: no usable credential, the Cloud gateway URL without a cloud_id, and a cloud_id set against any other host. HTML error pages are condensed to their message rather than dumped whole, and a non-JSON body reports what answered and where. 1.0.0 — Initial release: JQL ingestion + query, full issue CRUD and transitions, comments, links, attachments, fields/users, and agile board/sprint/epic listing. Cloud (API v3, ADF bodies) and On-Prem (API v2) supported."
category: ticketing
# Per-instance configuration. For Jira Cloud set cloud_id (found at
# admin.atlassian.com/s/<cloud_id>/users) and keep the default server_url; for
# On-Prem/Data Center leave cloud_id empty and set server_url to your Jira URL.
# Authentication: Basic (username = account email + api_key = API token) OR a
# Personal Access Token (pat). Provide only one method.
config_schema:
properties:
server_url:
type: string
description: "Base URL. Jira Cloud: keep the default and set cloud_id. On-Prem/Data Center: your own Jira URL, e.g. https://jira.example.com, with cloud_id left empty."
default: https://api.atlassian.com/ex/jira
cloud_id:
type: string
description: "Jira Cloud ID, found at admin.atlassian.com/s/<cloud_id>/users. Required alongside the Cloud gateway URL; leave empty for On-Prem/Data Center."
username:
type: string
description: "Account email (Basic auth, Jira Cloud). Pairs with api_key: both must be set for Basic authentication to be used."
api_key:
type: string
description: "API token (Basic auth, Jira Cloud). Created at id.atlassian.com/manage-profile/security/api-tokens. Pairs with username."
x-soar-sensitive: true
pat:
type: string
description: "Personal Access Token (On-Prem/Data Center only). Used when username and api_key are not both set. Leave empty on Cloud."
x-soar-sensitive: true
required:
- server_url
commands:
# ── Ingestion / search ────────────────────────────────────────────────────
- id: get_incidents
name: jira-get-incidents
description: "Fetch Jira issues matching a JQL query for ingestion. Returns {result:[...flattened issues...]}; use result as the alert rule results path."
risk: read
inputs_schema:
properties:
query: { type: string, description: "JQL selecting the issues to ingest, e.g. project = SOC AND status != Done. Empty means every issue the account can read. The fetch appends its own created >= watermark clause and ORDER BY created ASC — do not write either yourself." }
after: { type: string, description: "Only issues created at or after this instant: ISO8601 like 2026-09-01T14:00:00Z, or an epoch in seconds or milliseconds. Leave empty — the alert rule fills it with the previous run's watermark." }
max: { type: number, description: "Issues per run, default 50. The fetch makes one call and does not page, so a run that would exceed this silently drops the rest: raise it, or shorten the rule's interval." }
required: []
outputs_schema: { properties: {} }
ingest:
results_path: result
dedup_key: id
incremental_field: after
- id: query_issues
name: jira-query-issues
description: "Run a JQL query and return flattened issues."
risk: read
inputs_schema:
properties:
query: { type: string, description: "JQL, e.g. project = SOC AND created >= -7d ORDER BY created DESC. Unlike the ingestion fetch, the ordering here is yours to set." }
max_results: { type: number, description: "Issues per page, default 50." }
next_page_token: { type: string, description: "Cloud only. The nextPageToken from the previous response, to get the page after it. Empty for the first page." }
start_at: { type: number, description: "On-Prem only. Index of the first issue: 0, then 50, then 100… Cloud pages with next_page_token instead." }
required: [query]
outputs_schema: { properties: {} }
- id: get_issue
name: jira-get-issue
description: "Retrieve a single issue by ID or key (flattened)."
risk: read
inputs_schema:
properties:
issue_id: { type: string, description: "Numeric issue ID, e.g. 10042 — the id field the fetch returns. Give this or issue_key." }
issue_key: { type: string, description: "Issue key as shown in Jira, e.g. SOC-1423. Give this or issue_id." }
required: []
outputs_schema: { properties: {} }
# ── Issue lifecycle ───────────────────────────────────────────────────────
- id: create_issue
name: jira-create-issue
description: "Create a new issue. Provide project_key (or project_name), issue_type_name (or issue_type_id) and a summary."
inputs_schema:
properties:
project_key: { type: string, description: "Project key — the prefix of its issue keys, so SOC for SOC-1423. Give this or project_name." }
project_name: { type: string, description: "Project display name, e.g. Security Operations. It must match exactly one project. Give this or project_key, which is the faster path." }
issue_type_name: { type: string, description: "Issue type as the target project names it, e.g. Task, Bug, Incident. Types are per-project. Give this or issue_type_id." }
issue_type_id: { type: string, description: "Numeric issue type ID, e.g. 10004. Give this or issue_type_name, which is usually easier to read." }
summary: { type: string, description: "The issue title, one line. This is what shows in every Jira list." }
description: { type: string, description: "Body text. Write plain text: it is converted to Atlassian Document Format on Cloud." }
priority: { type: string, description: "Priority name exactly as the project defines it, e.g. Highest, High, Medium. An unknown name is rejected." }
labels: { type: string, description: "Comma-separated, no space inside a label, e.g. soc,phishing. Unknown labels are created." }
components: { type: string, description: "Comma-separated, e.g. Network,Endpoint. Components must already exist in the project — Jira will not create them." }
assignee_id: { type: string, description: "Cloud: the account ID, e.g. 5b10a2844c20165700ede21g. get_id_by_attribute turns a name or email into one." }
assignee: { type: string, description: "On-Prem: the username, e.g. jdupont. get_id_by_attribute turns a name or email into one." }
due_date: { type: string, description: "Date only, yyyy-mm-dd, e.g. 2026-09-30." }
fields_json: { type: string, description: "Advanced. A JSON object merged into Jira's fields payload, for anything the boxes above do not cover, e.g. {\"customfield_10010\": \"SOC-2\"}. Its keys win over those boxes." }
required: [summary]
outputs_schema: { properties: {} }
- id: edit_issue
name: jira-edit-issue
description: "Edit an issue's fields, and/or move it with status/transition (see jira-list-transitions)."
inputs_schema:
properties:
issue_id: { type: string, description: "Numeric issue ID, e.g. 10042 — the id field the fetch returns. Give this or issue_key." }
issue_key: { type: string, description: "Issue key as shown in Jira, e.g. SOC-1423. Give this or issue_id." }
summary: { type: string, description: "Replacement title. Leave empty to keep the current one." }
description: { type: string, description: "Replacement body, plain text. Replaces the whole description; it does not append." }
priority: { type: string, description: "Priority name exactly as the project defines it, e.g. Highest, High, Medium. An unknown name is rejected." }
labels: { type: string, description: "Comma-separated, e.g. soc,phishing. Replaces the whole list: a label left out is removed." }
components: { type: string, description: "Comma-separated, e.g. Network,Endpoint. Replaces the whole list, and each must already exist in the project." }
assignee_id: { type: string, description: "Cloud: the account ID, e.g. 5b10a2844c20165700ede21g. get_id_by_attribute turns a name or email into one." }
assignee: { type: string, description: "On-Prem: the username, e.g. jdupont. get_id_by_attribute turns a name or email into one." }
due_date: { type: string, description: "Date only, yyyy-mm-dd, e.g. 2026-09-30." }
status: { type: string, description: "Status you want the issue to end in, e.g. Done. The command finds a transition that leads there. Run list_transitions on the issue to see what it allows right now. Use this or transition, not both." }
transition: { type: string, description: "Transition to apply by name, e.g. Start Progress — one of those list_transitions returns for this issue. Use this or status, not both." }
fields_json: { type: string, description: "Advanced. A JSON object merged into Jira's fields payload, for anything the boxes above do not cover, e.g. {\"customfield_10010\": \"SOC-2\"}. Its keys win over those boxes." }
required: []
outputs_schema: { properties: {} }
- id: delete_issue
name: jira-delete-issue
description: "Delete an issue (its sub-tasks are deleted too)."
inputs_schema:
properties:
issue_id: { type: string, description: "Numeric issue ID, e.g. 10042 — the id field the fetch returns. Give this or issue_key." }
issue_key: { type: string, description: "Issue key as shown in Jira, e.g. SOC-1423. Give this or issue_id." }
required: []
outputs_schema: { properties: {} }
- id: assign_issue
name: jira-assign-issue
description: "Assign an issue to a user (assignee_id for Cloud, assignee for On-Prem)."
inputs_schema:
properties:
issue_id: { type: string, description: "Numeric issue ID, e.g. 10042 — the id field the fetch returns. Give this or issue_key." }
issue_key: { type: string, description: "Issue key as shown in Jira, e.g. SOC-1423. Give this or issue_id." }
assignee_id: { type: string, description: "Cloud: the account ID, e.g. 5b10a2844c20165700ede21g. get_id_by_attribute turns a name or email into one." }
assignee: { type: string, description: "On-Prem: the username, e.g. jdupont. get_id_by_attribute turns a name or email into one." }
required: []
outputs_schema: { properties: {} }
- id: list_transitions
name: jira-list-transitions
description: "List the transitions available for an issue in its current status."
risk: read
inputs_schema:
properties:
issue_id: { type: string, description: "Numeric issue ID, e.g. 10042 — the id field the fetch returns. Give this or issue_key." }
issue_key: { type: string, description: "Issue key as shown in Jira, e.g. SOC-1423. Give this or issue_id." }
required: []
outputs_schema: { properties: {} }
# ── Comments ──────────────────────────────────────────────────────────────
- id: add_comment
name: jira-add-comment
description: "Add a comment to an issue."
inputs_schema:
properties:
issue_id: { type: string, description: "Numeric issue ID, e.g. 10042 — the id field the fetch returns. Give this or issue_key." }
issue_key: { type: string, description: "Issue key as shown in Jira, e.g. SOC-1423. Give this or issue_id." }
comment: { type: string, description: "Comment text, plain — it is converted to Atlassian Document Format on Cloud." }
visibility: { type: string, description: "Project role the comment is limited to, by name, e.g. Administrators. Empty means anyone who can see the issue can read it." }
required: [comment]
outputs_schema: { properties: {} }
- id: get_comments
name: jira-get-comments
description: "Return the comments of an issue."
risk: read
inputs_schema:
properties:
issue_id: { type: string, description: "Numeric issue ID, e.g. 10042 — the id field the fetch returns. Give this or issue_key." }
issue_key: { type: string, description: "Issue key as shown in Jira, e.g. SOC-1423. Give this or issue_id." }
limit: { type: number, description: "Comments to return, newest last, default 50." }
required: []
outputs_schema: { properties: {} }
- id: edit_comment
name: jira-edit-comment
description: "Edit an existing comment on an issue."
inputs_schema:
properties:
issue_id: { type: string, description: "Numeric issue ID, e.g. 10042 — the id field the fetch returns. Give this or issue_key." }
issue_key: { type: string, description: "Issue key as shown in Jira, e.g. SOC-1423. Give this or issue_id." }
comment_id: { type: string, description: "Numeric comment ID, e.g. 10231 — returned by get_comments." }
comment: { type: string, description: "Replacement text, plain. Replaces the comment entirely." }
visibility: { type: string, description: "Project role the comment is limited to, by name, e.g. Administrators. Empty means anyone who can see the issue can read it." }
required: [comment_id, comment]
outputs_schema: { properties: {} }
- id: delete_comment
name: jira-delete-comment
description: "Delete a comment from an issue."
inputs_schema:
properties:
issue_id: { type: string, description: "Numeric issue ID, e.g. 10042 — the id field the fetch returns. Give this or issue_key." }
issue_key: { type: string, description: "Issue key as shown in Jira, e.g. SOC-1423. Give this or issue_id." }
comment_id: { type: string, description: "Numeric comment ID, e.g. 10231 — returned by get_comments." }
required: [comment_id]
outputs_schema: { properties: {} }
# ── Links ─────────────────────────────────────────────────────────────────
- id: add_link
name: jira-add-link
description: "Add a remote web link (URL) to an issue."
inputs_schema:
properties:
issue_id: { type: string, description: "Numeric issue ID, e.g. 10042 — the id field the fetch returns. Give this or issue_key." }
issue_key: { type: string, description: "Issue key as shown in Jira, e.g. SOC-1423. Give this or issue_id." }
url: { type: string, description: "Full URL, scheme included, e.g. https://riposte.example.com/incidents/482." }
title: { type: string, description: "The clickable text on the issue, e.g. Riposte incident 482." }
summary: { type: string, description: "One line shown under the title. Optional." }
relationship: { type: string, description: "How the link reads on the issue, e.g. causes, relates to, documents. Free text; empty leaves Jira's default wording." }
required: [url, title]
outputs_schema: { properties: {} }
- id: link_issues
name: jira-link-issues
description: "Create a link between two issues (see jira-get-link-types for link_type names)."
inputs_schema:
properties:
inward_issue: { type: string, description: "One end of the link, key or numeric ID, e.g. SOC-1423. get_link_types gives each type's inward and outward wording, which tells you which issue goes on which side." }
outward_issue: { type: string, description: "The other end, key or numeric ID, e.g. SOC-1500. See get_link_types for which side is which." }
link_type: { type: string, description: "Link type by name, e.g. Blocks, Relates, Duplicate — exactly as get_link_types returns it." }
comment: { type: string, description: "Comment recorded alongside the link. Optional." }
required: [inward_issue, outward_issue, link_type]
outputs_schema: { properties: {} }
- id: get_link_types
name: jira-get-link-types
description: "List all issue link types."
risk: read
inputs_schema:
properties: {}
required: []
outputs_schema: { properties: {} }
# ── Attachments ───────────────────────────────────────────────────────────
- id: upload_file
name: jira-upload-file
description: "Attach a file to an issue (content provided as base64)."
inputs_schema:
properties:
issue_id: { type: string, description: "Numeric issue ID, e.g. 10042 — the id field the fetch returns. Give this or issue_key." }
issue_key: { type: string, description: "Issue key as shown in Jira, e.g. SOC-1423. Give this or issue_id." }
file_name: { type: string, description: "Name the file gets in Jira, e.g. report.pdf. Its extension decides the content type sent to Jira." }
content_base64: { type: string, description: "The file's bytes, base64-encoded. In a playbook this comes from an earlier block's file output rather than being typed." }
required: [file_name, content_base64]
outputs_schema: { properties: {} }
- id: get_attachment
name: jira-get-attachment
description: "Download an attachment's content by attachment ID (returned as base64)."
risk: read
inputs_schema:
properties:
attachment_id: { type: string, description: "Numeric attachment ID, e.g. 10520 — get_issue lists them under attachments." }
required: [attachment_id]
outputs_schema: { properties: {} }
- id: delete_attachment
name: jira-delete-attachment
description: "Delete an attachment by attachment ID."
inputs_schema:
properties:
attachment_id: { type: string, description: "Numeric attachment ID, e.g. 10520 — get_issue lists them under attachments." }
required: [attachment_id]
outputs_schema: { properties: {} }
# ── Fields / users ────────────────────────────────────────────────────────
- id: list_fields
name: jira-list-fields
description: "List the system and custom issue fields."
risk: read
inputs_schema:
properties:
limit: { type: number, description: "Fields per page, default 50." }
offset: { type: number, description: "Index of the first row, for paging: 0, then 50, then 100…" }
required: []
outputs_schema: { properties: {} }
- id: get_id_by_attribute
name: jira-get-id-by-attribute
description: "Resolve a user's account ID (Cloud) or username (On-Prem) from a display name or email."
risk: read
inputs_schema:
properties:
attribute: { type: string, description: "A display name or an email, e.g. Jean Dupont or jean.dupont@example.com. Returns the account ID (Cloud) or username (On-Prem) that the assignee boxes expect." }
max_results: { type: number, description: "How many matches to weigh before giving up on an exact one, default 50." }
required: [attribute]
outputs_schema: { properties: {} }
- id: get_user_info
name: jira-get-user-info
description: "Get a user's details (account_id for Cloud; key or username for On-Prem). With no identifier, returns the caller."
risk: read
inputs_schema:
properties:
account_id: { type: string, description: "Cloud: the account ID, e.g. 5b10a2844c20165700ede21g. One of the three is enough." }
key: { type: string, description: "On-Prem: the user key, e.g. JIRAUSER10100. One of the three is enough." }
username: { type: string, description: "On-Prem: the username, e.g. jdupont. One of the three is enough." }
required: []
outputs_schema: { properties: {} }
# ── Agile: boards / sprints / epics ───────────────────────────────────────
- id: board_list
name: jira-board-list
description: "List agile boards (optionally filter by name, project or type)."
risk: read
inputs_schema:
properties:
board_id: { type: string, description: "Numeric board ID to return on its own, e.g. 42. Empty lists them all." }
board_name: { type: string, description: "Keep only boards whose name contains this text, e.g. SOC." }
project_key_id: { type: string, description: "Keep only boards of one project, by key or numeric ID, e.g. SOC." }
type: { type: string, description: "One of scrum, kanban or simple. Empty returns every type." }
limit: { type: number, description: "Boards per page, default 50." }
offset: { type: number, description: "Index of the first row, for paging: 0, then 50, then 100…" }
required: []
outputs_schema: { properties: {} }
- id: board_issue_list
name: jira-board-issue-list
description: "List the issues of a board (flattened)."
risk: read
inputs_schema:
properties:
board_id: { type: string, description: "Numeric board ID, e.g. 42 — returned by board_list." }
jql_query: { type: string, description: "Extra JQL narrowing the result, e.g. status = \"In Progress\" AND assignee IS EMPTY. Applied on top of the filter this list already has." }
limit: { type: number, description: "Issues per page, default 50." }
offset: { type: number, description: "Index of the first row, for paging: 0, then 50, then 100…" }
required: [board_id]
outputs_schema: { properties: {} }
- id: board_sprint_list
name: jira-board-sprint-list
description: "List the sprints of a board."
risk: read
inputs_schema:
properties:
board_id: { type: string, description: "Numeric board ID, e.g. 42 — returned by board_list." }
limit: { type: number, description: "Sprints per page, default 50." }
offset: { type: number, description: "Index of the first row, for paging: 0, then 50, then 100…" }
required: [board_id]
outputs_schema: { properties: {} }
- id: sprint_issue_list
name: jira-sprint-issue-list
description: "List the issues of a sprint (flattened)."
risk: read
inputs_schema:
properties:
sprint_id: { type: string, description: "Numeric sprint ID, e.g. 137 — returned by board_sprint_list." }
jql_query: { type: string, description: "Extra JQL narrowing the result, e.g. status = \"In Progress\" AND assignee IS EMPTY. Applied on top of the filter this list already has." }
limit: { type: number, description: "Issues per page, default 50." }
offset: { type: number, description: "Index of the first row, for paging: 0, then 50, then 100…" }
required: [sprint_id]
outputs_schema: { properties: {} }
- id: epic_issue_list
name: jira-epic-issue-list
description: "List the issues that belong to an epic (flattened)."
risk: read
inputs_schema:
properties:
epic_id: { type: string, description: "Numeric epic ID, e.g. 10310. Give this or epic_key." }
epic_key: { type: string, description: "Epic key, e.g. SOC-900. Give this or epic_id." }
jql_query: { type: string, description: "Extra JQL narrowing the result, e.g. status = \"In Progress\" AND assignee IS EMPTY. Applied on top of the filter this list already has." }
limit: { type: number, description: "Issues per page, default 50." }
offset: { type: number, description: "Index of the first row, for paging: 0, then 50, then 100…" }
required: []
outputs_schema: { properties: {} }
- id: test_connection
name: jira-test-connection
description: "Verify connectivity and credentials by reading the current user (used by the Test button)."
risk: read
inputs_schema:
properties: {}
required: []
outputs_schema: { properties: {} }
ingestion:
command: get_incidents
mapper: get_incidents
default_incident_type: "Jira Issue"