Skip to content

Add ticket tag management to Zendesk integration #17609

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Jul 22, 2025
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 48 additions & 0 deletions components/zendesk/actions/add-ticket-tags/add-ticket-tags.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import app from "../../zendesk.app.mjs";

export default {
key: "zendesk-add-ticket-tags",
name: "Add Ticket Tags",
description: "Add tags to a ticket (appends to existing tags). [See the documentation](https://developer.zendesk.com/api-reference/ticketing/ticket-management/tags/#add-tags).",
type: "action",
version: "0.0.1",
props: {
app,
ticketId: {
propDefinition: [
app,
"ticketId",
],
},
ticketTags: {
propDefinition: [
app,
"ticketTags",
],
description: "Array of tags to add to the ticket. These will be appended to any existing tags.",
},
customSubdomain: {
propDefinition: [
app,
"customSubdomain",
],
},
},
async run({ $: step }) {
const {
ticketId,
ticketTags,
customSubdomain,
} = this;

const response = await this.app.addTicketTags({
step,
ticketId,
tags: ticketTags,
customSubdomain,
});

step.export("$summary", `Successfully added ${ticketTags.length} tag(s) to ticket ${ticketId}`);
return response;
},
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import app from "../../zendesk.app.mjs";

export default {
key: "zendesk-remove-ticket-tags",
name: "Remove Ticket Tags",
description: "Remove specific tags from a ticket. [See the documentation](https://developer.zendesk.com/api-reference/ticketing/ticket-management/tags/#remove-tags).",
type: "action",
version: "0.0.1",
props: {
app,
ticketId: {
propDefinition: [
app,
"ticketId",
],
},
ticketTags: {
propDefinition: [
app,
"ticketTags",
],
description: "Array of tags to remove from the ticket.",
},
customSubdomain: {
propDefinition: [
app,
"customSubdomain",
],
},
},
async run({ $: step }) {
const {
ticketId,
ticketTags,
customSubdomain,
} = this;

const response = await this.app.removeTicketTags({
step,
ticketId,
tags: ticketTags,
customSubdomain,
});

step.export("$summary", `Successfully removed ${ticketTags.length} tag(s) from ticket ${ticketId}`);
return response;
},
};
47 changes: 47 additions & 0 deletions components/zendesk/actions/set-ticket-tags/set-ticket-tags.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import app from "../../zendesk.app.mjs";

export default {
key: "zendesk-set-ticket-tags",
name: "Set Ticket Tags",
description: "Set tags on a ticket (replaces all existing tags). [See the documentation](https://developer.zendesk.com/api-reference/ticketing/ticket-management/tags/#set-tags).",
type: "action",
version: "0.0.1",
props: {
app,
ticketId: {
propDefinition: [
app,
"ticketId",
],
},
ticketTags: {
propDefinition: [
app,
"ticketTags",
],
},
customSubdomain: {
propDefinition: [
app,
"customSubdomain",
],
},
},
async run({ $: step }) {
const {
ticketId,
ticketTags,
customSubdomain,
} = this;

const response = await this.app.setTicketTags({
step,
ticketId,
tags: ticketTags,
customSubdomain,
});

step.export("$summary", `Successfully set ${ticketTags.length} tag(s) on ticket ${ticketId}`);
return response;
},
};
77 changes: 74 additions & 3 deletions components/zendesk/actions/update-ticket/update-ticket.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ import app from "../../zendesk.app.mjs";
export default {
key: "zendesk-update-ticket",
name: "Update Ticket",
description: "Updates a ticket. [See the documentation](https://developer.zendesk.com/api-reference/ticketing/tickets/tickets/#update-ticket).",
description: "Updates a ticket and optionally manages tags. [See the documentation](https://developer.zendesk.com/api-reference/ticketing/tickets/tickets/#update-ticket).",
type: "action",
version: "0.1.3",
version: "0.1.4",
props: {
app,
ticketId: {
Expand Down Expand Up @@ -44,6 +44,33 @@ export default {
"customSubdomain",
],
},
ticketTags: {
propDefinition: [
app,
"ticketTags",
],
},
tagAction: {
type: "string",
label: "Tag Action",
description: "How to handle the tags: set (replace all existing tags), add (append to existing tags), or remove (remove specified tags)",
options: [
{
label: "Set Tags (Replace All)",
value: "set",
},
{
label: "Add Tags (Append)",
value: "add",
},
{
label: "Remove Tags",
value: "remove",
},
],
optional: true,
default: "set",
},
},
methods: {
updateTicket({
Expand All @@ -63,6 +90,8 @@ export default {
ticketSubject,
ticketStatus,
customSubdomain,
ticketTags,
tagAction,
} = this;

const response = await this.updateTicket({
Expand All @@ -81,8 +110,50 @@ export default {
},
});

step.export("$summary", `Successfully updated ticket with ID ${response.ticket.id}`);
// Handle tag operations if tags are provided
if (ticketTags && ticketTags.length > 0) {
let tagResponse;

switch (tagAction) {
case "add":
tagResponse = await this.app.addTicketTags({
step,
ticketId,
tags: ticketTags,
customSubdomain,
});
break;
case "remove":
tagResponse = await this.app.removeTicketTags({
step,
ticketId,
tags: ticketTags,
customSubdomain,
});
break;
case "set":
default:
tagResponse = await this.app.setTicketTags({
step,
ticketId,
tags: ticketTags,
customSubdomain,
});
break;
Comment on lines +156 to +164
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Remove redundant case clause.

The case "set": is redundant since it performs the same action as the default case. This creates unnecessary code duplication.

Apply this diff to fix the issue:

-      case "set":
-      default:
+      default: // handles "set" and any other values
         tagResponse = await this.app.setTicketTags({
           step,
           ticketId,
           tags: ticketTags,
           customSubdomain,
         });
         break;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
case "set":
default:
tagResponse = await this.app.setTicketTags({
step,
ticketId,
tags: ticketTags,
customSubdomain,
});
break;
default: // handles "set" and any other values
tagResponse = await this.app.setTicketTags({
step,
ticketId,
tags: ticketTags,
customSubdomain,
});
break;
🧰 Tools
🪛 Biome (1.9.4)

[error] 134-134: Useless case clause.

because the default clause is present:

Unsafe fix: Remove the useless case.

(lint/complexity/noUselessSwitchCase)

🤖 Prompt for AI Agents
In components/zendesk/actions/update-ticket/update-ticket.mjs around lines 134
to 142, the case "set": is redundant because it executes the same code as the
default case. Remove the case "set": line and keep only the default case to
eliminate duplication and simplify the switch statement.

}

// Include tag information in summary
const tagSummary = `and ${tagAction === "set" ? "set" : tagAction === "add" ? "added" : "removed"} ${ticketTags.length} tag(s)`;
step.export("$summary", `Successfully updated ticket with ID ${response.ticket.id} ${tagSummary}`);

// Include tag response in the return data
return {
ticket: response,
tags: tagResponse,
};
}

step.export("$summary", `Successfully updated ticket with ID ${response.ticket.id}`);
return response;
},
};
69 changes: 69 additions & 0 deletions components/zendesk/zendesk.app.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,12 @@ export default {
description: "For Enterprise Zendesk accounts: optionally specify the subdomain to use. This will override the subdomain that was provided when connecting your Zendesk account to Pipedream. For example, if you Zendesk URL is https://examplehelp.zendesk.com, your subdomain is `examplehelp`",
optional: true,
},
ticketTags: {
type: "string[]",
label: "Tags",
description: "Array of tags to apply to the ticket. These will replace any existing tags on the ticket.",
optional: true,
},
},
methods: {
getUrl(path, customSubdomain) {
Expand Down Expand Up @@ -300,5 +306,68 @@ export default {
args.params.page += 1;
}
},
/**
* Set tags on a ticket (replaces all existing tags)
* @param {object} args - Arguments object
* @param {string} args.ticketId - The ticket ID
* @param {string[]} args.tags - Array of tags to set
* @param {string} args.customSubdomain - Optional custom subdomain
* @returns {Promise<object>} API response
*/
setTicketTags({
ticketId, tags, customSubdomain, ...args
}) {
return this.makeRequest({
method: "PUT",
path: `/tickets/${ticketId}/tags.json`,
customSubdomain,
data: {
tags,
},
...args,
});
},
/**
* Add tags to a ticket (appends to existing tags)
* @param {object} args - Arguments object
* @param {string} args.ticketId - The ticket ID
* @param {string[]} args.tags - Array of tags to add
* @param {string} args.customSubdomain - Optional custom subdomain
* @returns {Promise<object>} API response
*/
addTicketTags({
ticketId, tags, customSubdomain, ...args
}) {
return this.makeRequest({
method: "POST",
path: `/tickets/${ticketId}/tags.json`,
customSubdomain,
data: {
tags,
},
...args,
});
},
/**
* Remove specific tags from a ticket
* @param {object} args - Arguments object
* @param {string} args.ticketId - The ticket ID
* @param {string[]} args.tags - Array of tags to remove
* @param {string} args.customSubdomain - Optional custom subdomain
* @returns {Promise<object>} API response
*/
removeTicketTags({
ticketId, tags, customSubdomain, ...args
}) {
return this.makeRequest({
method: "DELETE",
path: `/tickets/${ticketId}/tags.json`,
customSubdomain,
data: {
tags,
},
...args,
});
},
},
};