Add Activepieces integration for workflow automation

- Add Activepieces fork with SmoothSchedule custom piece
- Create integrations app with Activepieces service layer
- Add embed token endpoint for iframe integration
- Create Automations page with embedded workflow builder
- Add sidebar visibility fix for embed mode
- Add list inactive customers endpoint to Public API
- Include SmoothSchedule triggers: event created/updated/cancelled
- Include SmoothSchedule actions: create/update/cancel events, list resources/services/customers

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
poduck
2025-12-18 22:59:37 -05:00
parent 9848268d34
commit 3aa7199503
16292 changed files with 1284892 additions and 4708 deletions

View File

@@ -0,0 +1,34 @@
import { createAction, Property } from '@activepieces/pieces-framework';
import { intercomAuth } from '../..';
import { commonProps, intercomClient } from '../common';
import { conversationIdProp } from '../common/props';
export const addNoteToConversationAction = createAction({
auth: intercomAuth,
name: 'addNoteToConversation',
displayName: 'Add note to conversation',
description: 'Add a note (for other admins) to an existing conversation',
props: {
from: commonProps.admins({ displayName: 'From (Admin)', required: true }),
conversationId:conversationIdProp('Conversation ID', true),
body: Property.ShortText({
displayName: 'Message Body',
required: true,
}),
},
async run(context) {
const client = intercomClient(context.auth);
const response = await client.conversations.reply({
conversation_id: context.propsValue.conversationId!,
body: {
type: 'admin',
message_type: 'note',
body: context.propsValue.body,
admin_id: context.propsValue.from,
},
});
return response;
},
});

View File

@@ -0,0 +1,44 @@
import { intercomAuth } from '../../index';
import { createAction, Property } from '@activepieces/pieces-framework';
import { intercomClient } from '../common';
export const addNoteToUserAction = createAction({
auth: intercomAuth,
name: 'add-note-to-user',
displayName: 'Add Note',
description: 'Add a note to a user',
props: {
email: Property.ShortText({
displayName: 'Email',
required: true,
}),
body: Property.LongText({
displayName: 'Note Text',
required: true,
}),
},
async run(context) {
const client = intercomClient(context.auth);
const contactResponse = await client.contacts.search({
query: {
field: 'email',
operator: '=',
value: context.propsValue.email,
},
});
if (contactResponse.data.length === 0) {
throw new Error('Could not find user with this email address.');
}
const contactId = contactResponse.data[0].id;
const noteResponse = await client.notes.create({
contact_id: contactId,
body: context.propsValue.body,
});
return noteResponse;
},
});

View File

@@ -0,0 +1,47 @@
import { intercomAuth } from '../../index';
import { createAction, Property } from '@activepieces/pieces-framework';
import { companyIdProp } from '../common/props';
import { intercomClient } from '../common';
export const addOrRemoveTagOnCompanyAction = createAction({
auth: intercomAuth,
name: 'add-or-remove-tag-on-company',
displayName: 'Add/Remove Tag on Company',
description: 'Attach or remove a tag from a specific company.',
props: {
companyId: companyIdProp('Company ID', true),
tagName: Property.ShortText({
displayName: 'Tag Name',
required: true,
}),
untag: Property.Checkbox({
displayName: 'Untag ?',
required: false,
defaultValue: false,
}),
},
async run(context) {
const client = intercomClient(context.auth);
if (context.propsValue.untag) {
const company = await client.companies.find({ company_id: context.propsValue.companyId! });
const userDefinedCompanyId = company.company_id;
const response = await client.tags.create({
name: context.propsValue.tagName,
companies: [
{ id: context.propsValue.companyId!, untag: true, company_id: userDefinedCompanyId },
],
});
return response;
}
const response = await client.tags.create({
name: context.propsValue.tagName,
companies: [{ id: context.propsValue.companyId }],
});
return response;
},
});

View File

@@ -0,0 +1,39 @@
import { intercomAuth } from '../../index';
import { createAction, Property } from '@activepieces/pieces-framework';
import { contactIdProp, tagIdProp } from '../common/props';
import { intercomClient } from '../common';
export const addOrRemoveTagOnContactAction = createAction({
auth: intercomAuth,
name: 'add-or-remove-tag-on-contact',
displayName: 'Add/Remove Tag on Contact',
description: 'Attach or remove a tag from a specific contact.',
props: {
contactId: contactIdProp('Contact ID','user', true),
tagId: tagIdProp('Tag Name', true),
untag: Property.Checkbox({
displayName: 'Untag ?',
required: false,
defaultValue: false,
}),
},
async run(context) {
const client = intercomClient(context.auth);
if (context.propsValue.untag) {
const response = await client.tags.untagContact({
contact_id: context.propsValue.contactId!,
tag_id: context.propsValue.tagId!,
});
return response;
}
const response = await client.tags.tagContact({
contact_id: context.propsValue.contactId!,
id: context.propsValue.tagId!,
});
return response;
},
});

View File

@@ -0,0 +1,43 @@
import { intercomAuth } from '../../index';
import { createAction, Property } from '@activepieces/pieces-framework';
import { conversationIdProp, tagIdProp } from '../common/props';
import { intercomClient } from '../common';
export const addOrRemoveTagOnConversationAction = createAction({
auth: intercomAuth,
name: 'add-or-remove-tag-on-conversation',
displayName: 'Add/Remove Tag on Conversation',
description: 'Attach or remove a tag from a specific conversation.',
props: {
conversationId: conversationIdProp('Conversation ID', true),
tagId: tagIdProp('Tag', true),
untag: Property.Checkbox({
displayName: 'Untag ?',
required: false,
defaultValue: false,
}),
},
async run(context) {
const client = intercomClient(context.auth);
const admin = await client.admins.identify();
const adminId = admin.id;
if (context.propsValue.untag) {
const response = await client.tags.untagConversation({
conversation_id: context.propsValue.conversationId!,
tag_id: context.propsValue.tagId!,
admin_id: adminId,
});
return response;
}
const response = await client.tags.tagConversation({
conversation_id: context.propsValue.conversationId!,
id: context.propsValue.tagId!,
admin_id: adminId,
});
return response;
},
});

View File

@@ -0,0 +1,59 @@
import { intercomAuth } from '../../index';
import { createAction, Property } from '@activepieces/pieces-framework';
import { commonProps, intercomClient } from '../common';
import { collectionIdProp } from '../common/props';
export const createArticleAction = createAction({
auth: intercomAuth,
name: 'create-article',
displayName: 'Create Article',
description: 'Creates a new article in your Help Center.',
props: {
title: Property.LongText({
displayName: 'Title',
required: true,
}),
description: Property.ShortText({
displayName: 'Description',
required: false,
}),
body: Property.LongText({
displayName: 'Body',
required: false,
}),
authorId: commonProps.admins({ displayName: 'Author', required: true }),
state: Property.StaticDropdown({
displayName: 'State',
required: true,
defaultValue: 'draft',
options: {
disabled: false,
options: [
{ label: 'Draft', value: 'draft' },
{ label: 'Published', value: 'published' },
],
},
}),
collectionId: collectionIdProp('Parent Collection', false),
},
async run(context) {
const { authorId, collectionId, title, description, body, state } = context.propsValue;
if (!authorId) {
throw new Error('Author is required');
}
const client = intercomClient(context.auth);
const response = await client.articles.create({
title,
description,
body,
author_id: Number(authorId),
state: state as 'published' | 'draft',
parent_id: collectionId ? Number(collectionId) : undefined,
});
return response;
},
});

View File

@@ -0,0 +1,83 @@
import { intercomAuth } from '../../index';
import {
createAction,
DropdownOption,
PiecePropValueSchema,
Property,
} from '@activepieces/pieces-framework';
import { intercomClient } from '../common';
export const createConversationAction = createAction({
auth: intercomAuth,
name: 'create-conversation',
displayName: 'Create Conversation',
description: 'Creates a new conversation from a contact.',
props: {
contactType: Property.StaticDropdown({
displayName: 'Contact Type',
required: true,
defaultValue: 'user',
options: {
disabled: false,
options: [
{ value: 'user', label: 'User' },
{ value: 'lead', label: 'Lead' },
],
},
}),
contactId: Property.Dropdown({
auth: intercomAuth,
displayName: 'Contact ID',
required: true,
refreshers: ['contactType'],
options: async ({ auth, contactType }) => {
if (!auth || !contactType) {
return {
options: [],
disabled: true,
placeholder: 'Please connect your account first.',
};
}
const type = contactType as 'user' | 'lead';
const authValue = auth as PiecePropValueSchema<typeof intercomAuth>;
const client = intercomClient(authValue);
const response = await client.contacts.list();
const options: DropdownOption<string>[] = [];
for await (const contact of response) {
if (contact.role === type) {
options.push({
value: contact.id,
label: `${contact.name ?? ''}, ${contact.email}, ${contact.external_id ?? ''}`,
});
}
}
return {
disabled: false,
options,
};
},
}),
body: Property.LongText({
displayName: 'Message Body',
required: true,
}),
},
async run(context) {
const { contactId, body, contactType } = context.propsValue;
const client = intercomClient(context.auth);
const response = await client.conversations.create({
body,
from: {
type: contactType as 'lead' | 'user' | 'contact',
id: contactId,
},
});
return response;
},
});

View File

@@ -0,0 +1,57 @@
import { intercomAuth } from '../../index';
import { createAction } from '@activepieces/pieces-framework';
import { intercomClient } from '../common';
import {
companyIdProp,
contactIdProp,
ticketPropertiesProp,
ticketTypeIdProp,
} from '../common/props';
import dayjs from 'dayjs';
export const createTicketAction = createAction({
auth: intercomAuth,
name: 'create-ticket',
displayName: 'Create Ticket',
description: 'Creates a new ticket.',
props: {
ticketTypeId: ticketTypeIdProp('Ticket Type', true),
contactId: contactIdProp('Contact ID', null, true),
companyId: companyIdProp('Company ID', false),
ticketProperties: ticketPropertiesProp('Ticket Properties', true),
},
async run(context) {
const { ticketTypeId, contactId, companyId } = context.propsValue;
const ticketProperties = context.propsValue.ticketProperties ?? {};
if (!ticketTypeId) {
throw new Error('Ticket Type is required');
}
if (!contactId) {
throw new Error('Contact ID is required');
}
const client = intercomClient(context.auth);
const formattedProperties: Record<string, any> = {};
for (const key in ticketProperties) {
const value = ticketProperties[key];
// Check if value is a valid date string and convert it to a timestamp
if (typeof value === 'string' && dayjs(value).isValid()) {
formattedProperties[key] = dayjs(value).unix(); // Convert to timestamp
} else {
formattedProperties[key] = value;
}
}
const response = await client.tickets.create({
ticket_type_id: ticketTypeId,
contacts: [{ id: contactId }],
company_id: companyId,
ticket_attributes: formattedProperties,
});
return response;
},
});

View File

@@ -0,0 +1,95 @@
import { intercomAuth } from '../../index';
import { createAction, Property } from '@activepieces/pieces-framework';
import { intercomClient } from '../common';
import dayjs from 'dayjs';
export const createOrUpdateLeadAction = createAction({
auth: intercomAuth,
name: 'create-or-update-lead',
displayName: 'Create or Update Lead',
description: 'Create or update an Intercom lead.If an ID is provided, the lead will be updated.',
props: {
leadId: Property.ShortText({
displayName: 'Lead ID',
required: false,
}),
name: Property.ShortText({
displayName: 'Full Name',
required: false,
}),
email: Property.ShortText({
displayName: 'Email',
required: false,
}),
phone: Property.ShortText({
displayName: 'Phone',
required: false,
}),
unsubscribe: Property.Checkbox({
displayName: 'Unsubscribed From Emails',
required: false,
}),
createdAt: Property.DateTime({
displayName: 'Created At',
required: false,
}),
customAttributes: Property.Object({
displayName: 'Custom Attributes',
required: false,
}),
},
async run(context) {
const { leadId, name, email, phone, unsubscribe, createdAt, customAttributes } =
context.propsValue;
const client = intercomClient(context.auth);
if (leadId) {
const lead = await client.contacts.search({
query: {
operator: 'AND',
value: [
{
field: 'id',
operator: '=',
value: leadId,
},
{
field: 'role',
operator: '=',
value: 'lead',
},
],
},
pagination: { per_page: 1 },
});
if (lead.data.length === 0) {
throw new Error('Could not find lead with this id.');
}
const response = await client.contacts.update({
contact_id: lead.data[0].id,
name: name,
email: email,
phone: phone,
unsubscribed_from_emails: unsubscribe,
custom_attributes: customAttributes,
signed_up_at: createdAt ? dayjs(createdAt).unix() : undefined,
});
return response;
}
const response = await client.contacts.create({
role: 'lead',
name: name,
email: email,
phone: phone,
unsubscribed_from_emails: unsubscribe,
custom_attributes: customAttributes,
signed_up_at: createdAt ? dayjs(createdAt).unix() : undefined,
});
return response;
},
});

View File

@@ -0,0 +1,90 @@
import { intercomAuth } from '../../index';
import { createAction, Property } from '@activepieces/pieces-framework';
import { intercomClient } from '../common';
import dayjs from 'dayjs';
export const createOrUpdateUserAction = createAction({
auth: intercomAuth,
name: 'create-or-update-user',
displayName: 'Create/Update User',
description: 'Update a user within intercom given an email address.',
props: {
email: Property.ShortText({
displayName: 'Lookup Email',
required: true,
}),
name: Property.ShortText({
displayName: 'Full Name',
required: false,
}),
userId: Property.ShortText({
displayName: 'User ID',
required: false,
}),
phone: Property.ShortText({
displayName: 'Phone',
required: false,
}),
createdAt: Property.DateTime({
displayName: 'Created At',
required: false,
}),
customAttributes: Property.Object({
displayName: 'Custom Attributes',
required: false,
}),
},
async run(context) {
const client = intercomClient(context.auth);
const contact = await client.contacts.search({
query: {
operator: 'AND',
value: [
{
field: 'email',
operator: '=',
value: context.propsValue.email,
},
{
field: 'role',
operator: '=',
value: 'user',
},
],
},
pagination: { per_page: 1 },
});
if (contact.data.length === 0) {
const response = await client.contacts.create({
role: 'user',
email: context.propsValue.email,
name: context.propsValue.name,
custom_attributes: context.propsValue.customAttributes,
signed_up_at: context.propsValue.createdAt
? dayjs(context.propsValue.createdAt).unix()
: undefined,
external_id: context.propsValue.userId,
phone: context.propsValue.phone,
});
return response;
}
const contactId = contact.data[0].id;
const response = await client.contacts.update({
contact_id: contactId,
name: context.propsValue.name,
custom_attributes: context.propsValue.customAttributes,
signed_up_at: context.propsValue.createdAt
? dayjs(context.propsValue.createdAt).unix()
: undefined,
external_id: context.propsValue.userId,
phone: context.propsValue.phone,
});
return response;
},
});

View File

@@ -0,0 +1,49 @@
import { intercomAuth } from '../../index';
import { createAction, Property } from '@activepieces/pieces-framework';
import { intercomClient } from '../common';
import dayjs from 'dayjs';
export const createUserAction = createAction({
auth: intercomAuth,
name: 'create-user',
displayName: 'Create User',
description: 'Creates a new user.',
props: {
email: Property.ShortText({
displayName: 'Email',
required: true,
}),
createdAt: Property.DateTime({
displayName: 'Created At',
required: false,
}),
userId: Property.ShortText({
displayName: 'User ID',
required: false,
}),
name: Property.ShortText({
displayName: 'Full Name',
required: false,
}),
customAttributes: Property.Object({
displayName: 'Custom Attributes',
required: false,
}),
},
async run(context) {
const client = intercomClient(context.auth);
const response = await client.contacts.create({
role: 'user',
email: context.propsValue.email,
name: context.propsValue.name,
custom_attributes: context.propsValue.customAttributes,
signed_up_at: context.propsValue.createdAt
? dayjs(context.propsValue.createdAt).unix()
: undefined,
external_id: context.propsValue.userId,
});
return response;
},
});

View File

@@ -0,0 +1,44 @@
import { intercomAuth } from '../../index';
import { createAction, Property } from '@activepieces/pieces-framework';
import { intercomClient } from '../common';
export const findCompanyAction = createAction({
auth: intercomAuth,
name: 'find-company',
displayName: 'Find Company',
description: 'Finds an existing company.',
props: {
searchField: Property.StaticDropdown({
displayName: 'Search Field',
required: true,
options: {
disabled: false,
options: [
{ label: 'Name', value: 'name' },
{ label: 'Company ID', value: 'company_id' },
],
},
}),
searchValue: Property.ShortText({
displayName: 'Search Value',
required: true,
}),
},
async run(context) {
const { searchField, searchValue } = context.propsValue;
const client = intercomClient(context.auth);
const companyResponse = await client.companies.retrieve({
company_id: searchField === 'company_id' ? searchValue : undefined,
name: searchField === 'name' ? searchValue : undefined,
per_page:1
})
return {
found: companyResponse.data.length > 0,
user: companyResponse.data.length > 0 ? companyResponse.data[0] : {},
};
},
});

View File

@@ -0,0 +1,114 @@
import { intercomAuth } from '../../index';
import { createAction, Property } from '@activepieces/pieces-framework';
import { intercomClient, Operator } from '../common';
import dayjs from 'dayjs';
export const findConversationAction = createAction({
auth: intercomAuth,
name: 'find-conversation',
displayName: 'Find Conversation',
description: 'Searches for conversations using various criteria',
props: {
searchField: Property.StaticDropdown({
displayName: 'Search Field',
required: true,
options: {
disabled: false,
options: [
{ label: 'Conversation ID', value: 'id' },
{ label: 'Subject', value: 'source.subject' },
{ label: 'Message Body', value: 'source.body' },
{ label: 'Author Email', value: 'source.author.email' },
{ label: 'Assigned Admin', value: 'admin_assignee_id' },
{ label: 'Team', value: 'team_assignee_id' },
{ label: 'Tag IDs', value: 'tag_ids' },
],
},
}),
matchType: Property.StaticDropdown({
displayName: 'Match Type',
required: true,
options: {
disabled: false,
options: [
{ label: 'Contains', value: 'contains' },
{ label: 'Equals', value: 'equals' },
{ label: 'Starts With', value: 'starts_with' },
],
},
}),
searchTerm: Property.ShortText({
displayName: 'Search Term',
required: true,
}),
status: Property.StaticDropdown({
displayName: 'Status',
required: false,
options: {
disabled: false,
options: [
{ label: 'Open', value: 'open' },
{ label: 'Closed', value: 'closed' },
],
},
}),
updateAfter: Property.DateTime({
displayName: 'Update After',
required: false,
}),
updateBefore: Property.DateTime({
displayName: 'Update Before',
required: false,
}),
},
async run(context) {
const { searchField, matchType, searchTerm, status, updateAfter, updateBefore } =
context.propsValue;
const operator = matchType === 'contains' ? '~' : matchType === 'starts_with' ? '^' : '=';
const client = intercomClient(context.auth);
const filter = [
{
field: searchField,
operator: operator as Operator,
value: searchTerm,
},
];
if (status) {
filter.push({
field: 'state',
operator: "=",
value: status,
});
}
if (updateAfter) {
filter.push({
field: 'updated_at',
operator: '>',
value: dayjs(updateAfter).unix().toString(),
});
}
if (updateBefore) {
filter.push({
field: 'updated_at',
operator: "<",
value: dayjs(updateBefore).unix().toString(),
});
}
const response = await client.conversations.search({
query: {
operator: 'AND',
value: filter,
},
});
return {
found: response.data.length > 0,
conversation: response.data.length > 0 ? response.data[0] : {},
};
},
});

View File

@@ -0,0 +1,57 @@
import { intercomAuth } from '../../index';
import { createAction, Property } from '@activepieces/pieces-framework';
import { intercomClient } from '../common';
export const findLeadAction = createAction({
auth: intercomAuth,
name: 'find-lead',
displayName: 'Find Lead',
description: 'Finds an existing lead.',
props: {
searchField: Property.StaticDropdown({
displayName: 'Search Field',
required: true,
options: {
disabled: false,
options: [
{ label: 'Email', value: 'email' },
{ label: 'ID', value: 'id' },
{ label: 'User ID', value: 'external_id' },
],
},
}),
searchValue: Property.ShortText({
displayName: 'Search Value',
required: true,
}),
},
async run(context) {
const { searchField, searchValue } = context.propsValue;
const client = intercomClient(context.auth);
const contactResponse = await client.contacts.search({
query: {
operator: 'AND',
value: [
{
field: searchField,
operator: '=',
value: searchValue,
},
{
field: 'role',
operator: '=',
value: 'lead',
},
],
},
pagination: { per_page: 1 },
});
return {
found: contactResponse.data.length > 0,
lead: contactResponse.data.length > 0 ? contactResponse.data[0] : {},
};
},
});

View File

@@ -0,0 +1,57 @@
import { intercomAuth } from '../../index';
import { createAction, Property } from '@activepieces/pieces-framework';
import { intercomClient } from '../common';
export const findUserAction = createAction({
auth: intercomAuth,
name: 'find-user',
displayName: 'Find User',
description: 'Finds an existing user.',
props: {
searchField: Property.StaticDropdown({
displayName: 'Search Field',
required: true,
options: {
disabled: false,
options: [
{ label: 'Email', value: 'email' },
{ label: 'ID', value: 'id' },
{ label: 'User ID', value: 'external_id' },
],
},
}),
searchValue: Property.ShortText({
displayName: 'Search Value',
required: true,
}),
},
async run(context) {
const { searchField, searchValue } = context.propsValue;
const client = intercomClient(context.auth);
const contactResponse = await client.contacts.search({
query: {
operator: 'AND',
value: [
{
field: searchField,
operator: '=',
value: searchValue,
},
{
field: 'role',
operator: '=',
value: 'user',
},
],
},
pagination: { per_page: 1 },
});
return {
found: contactResponse.data.length > 0,
user: contactResponse.data.length > 0 ? contactResponse.data[0] : {},
};
},
});

View File

@@ -0,0 +1,28 @@
import { intercomAuth } from '../../index';
import { createAction } from '@activepieces/pieces-framework';
import { conversationIdProp } from '../common/props';
import { intercomClient } from '../common';
export const getConversationAction = createAction({
auth: intercomAuth,
name: 'get-conversation',
displayName: 'Retrieve a Conversation',
description: 'Retrieves a specific conversation by ID.',
props: {
conversationId: conversationIdProp('Conversation ID', true),
},
async run(context) {
const { conversationId } = context.propsValue;
const client = intercomClient(context.auth);
if (!conversationId) {
throw new Error('Conversation ID is required');
}
const response = await client.conversations.find({
conversation_id: conversationId,
});
return response;
},
});

View File

@@ -0,0 +1,19 @@
import { intercomAuth } from "../../index";
import { createAction } from "@activepieces/pieces-framework";
import { intercomClient } from "../common";
export const listAllTagsAction = createAction({
auth:intercomAuth,
name:'list-all-tags',
displayName:'List Tags',
description:'List all tags.',
props:{},
async run(context){
const client = intercomClient(context.auth);
const response = await client.tags.list();
return response;
}
})

View File

@@ -0,0 +1,34 @@
import { createAction, Property } from '@activepieces/pieces-framework';
import { intercomAuth } from '../..';
import { commonProps, intercomClient } from '../common';
import { conversationIdProp } from '../common/props';
export const replyToConversation = createAction({
auth: intercomAuth,
name: 'replyToConversation',
displayName: 'Reply to conversation',
description: 'Reply (as an admin) to a conversation with a contact',
props: {
from: commonProps.admins({ displayName: 'From (Admin)', required: true }),
conversationId: conversationIdProp('Conversation ID', true),
body: Property.ShortText({
displayName: 'Message Body',
required: true,
}),
},
async run(context) {
const client = intercomClient(context.auth);
const response = await client.conversations.reply({
conversation_id: context.propsValue.conversationId!,
body: {
type: 'admin',
message_type: 'comment',
body: context.propsValue.body,
admin_id: context.propsValue.from,
},
});
return response;
},
});

View File

@@ -0,0 +1,87 @@
import { createAction, DynamicPropsValue, Property } from '@activepieces/pieces-framework';
import { commonProps, intercomClient } from '../common';
import { intercomAuth } from '../..';
export const sendMessageAction = createAction({
auth: intercomAuth,
description: 'Send a message to a contact (only allowed by admins)',
displayName: 'Send Message',
name: 'send_message',
props: {
message_type: Property.StaticDropdown({
displayName: 'Message Type',
options: {
options: [
{ value: 'email', label: 'Email' },
{ value: 'inapp', label: 'In App Chat' },
],
},
required: true,
defaultValue: 'email',
}),
email_required_fields: Property.DynamicProperties({
auth: intercomAuth,
displayName: 'Email Required Fields',
required: true,
refreshers: ['message_type'],
props: async ({ message_type }) => {
let fields: DynamicPropsValue = {};
if ((message_type as unknown as string) === 'email' || !message_type) {
fields = {
subject: Property.ShortText({
displayName: 'Subject',
required: true,
description: 'Email title',
}),
template: Property.StaticDropdown({
displayName: 'Template',
options: {
options: [
{ label: 'Personal', value: 'personal' },
{ label: 'Plain', value: 'plain' },
],
},
required: true,
defaultValue: 'personal',
description: 'Style of the email',
}),
};
}
return fields;
},
}),
from: commonProps.admins({ displayName: 'From (Admin)', required: true }),
to: commonProps.contacts({ displayName: 'To', required: true }),
body: Property.ShortText({
displayName: 'Message Body',
required: true,
}),
create_conversation_without_contact_reply: Property.Checkbox({
displayName: 'Create Conversation Without Contact Reply',
description:
'Whether a conversation should be opened in the inbox for the message without the contact replying. Defaults to false if not provided.',
required: false,
defaultValue: false,
}),
},
run: async (context) => {
const client = intercomClient(context.auth);
const user = await client.contacts.find({ contact_id: context.propsValue.to });
const response = await client.messages.create({
message_type: context.propsValue.message_type as 'email' | 'inapp',
from: { id: Number(context.propsValue.from), type: 'admin' },
to: {
id: context.propsValue.to,
type: user.role === 'user' ? 'user' : 'lead',
},
template: context.propsValue.email_required_fields['template'],
subject: context.propsValue.email_required_fields['subject'],
create_conversation_without_contact_reply:
context.propsValue.create_conversation_without_contact_reply,
body: context.propsValue.body,
});
return response;
},
});

View File

@@ -0,0 +1,100 @@
import { intercomAuth } from '../../index';
import { createAction, Property } from '@activepieces/pieces-framework';
import { commonProps, intercomClient } from '../common';
import { ticketIdProp, ticketPropertiesProp, ticketTypeIdProp } from '../common/props';
import { UpdateTicketRequest } from 'intercom-client/api';
import dayjs from 'dayjs';
export const updateTicketAction = createAction({
auth: intercomAuth,
name: 'update-ticket',
displayName: 'Update Ticket',
description: 'Updates an existing ticket.',
props: {
ticketTypeId: ticketTypeIdProp('Ticket Type', true),
ticketId: ticketIdProp('Ticket', true),
ticketProperties: ticketPropertiesProp('Ticket Properties', true),
isOpen: Property.Checkbox({
displayName: 'Is Open',
required: false,
}),
state: Property.StaticDropdown({
displayName: 'State',
required: false,
options: {
disabled: false,
options: [
{
value: 'in_progress',
label: 'In Progress',
},
{
value: 'waiting_on_customer',
label: 'Waiting on Customer',
},
{
value: 'resolved',
label: 'Resolved',
},
],
},
}),
snoozedTill: Property.DateTime({
displayName: 'Snoozed Until',
required: false,
}),
assignedAdminId: commonProps.admins({ displayName: 'Assigned Admin', required: false }),
},
async run(context) {
const { ticketTypeId, ticketId, isOpen, state, snoozedTill, assignedAdminId } =
context.propsValue;
const ticketProperties = context.propsValue.ticketProperties ?? {};
if (!ticketTypeId) {
throw new Error('Ticket Type is required');
}
if (!ticketId) {
throw new Error('Ticket ID is required');
}
const client = intercomClient(context.auth);
const request: UpdateTicketRequest = {
ticket_id: ticketId,
open: isOpen,
state: state as 'in_progress' | 'waiting_on_customer' | 'resolved' | undefined,
};
if (snoozedTill) {
request.snoozed_until = dayjs(snoozedTill).unix();
}
if (assignedAdminId) {
const admin = await client.admins.identify();
request.assignment = {
assignee_id: assignedAdminId,
admin_id: admin.id,
};
}
if (Object.keys(ticketProperties).length > 0) {
const formattedProperties: Record<string, any> = {};
for (const key in ticketProperties) {
const value = ticketProperties[key];
// Check if value is a valid date string and convert it to a timestamp
if (typeof value === 'string' && dayjs(value).isValid()) {
formattedProperties[key] = dayjs(value).unix(); // Convert to timestamp
} else {
formattedProperties[key] = value;
}
}
request.ticket_attributes = formattedProperties;
}
const response = await client.tickets.update(request);
return response;
},
});

View File

@@ -0,0 +1,109 @@
import { getAccessTokenOrThrow } from '@activepieces/pieces-common';
import { IntercomClient } from 'intercom-client';
import {
OAuth2PropertyValue,
OAuth2Props,
Property,
} from '@activepieces/pieces-framework';
import { intercomAuth } from '../../index';
export const intercomClient = (auth: OAuth2PropertyValue<OAuth2Props>) => {
const client = new IntercomClient({
token: getAccessTokenOrThrow(auth),
environment: `https://api.${auth.props?.['region']}.io`,
});
return client;
};
export const commonProps = {
admins: <R extends boolean>(options: { displayName: string; required: R }) =>
Property.Dropdown<string, R, typeof intercomAuth>({
auth: intercomAuth,
displayName: options.displayName,
required: options.required,
options: async ({ auth }) => {
if (!auth) {
return {
options: [],
disabled: true,
placeholder: 'Please connect your account first',
};
}
const client = intercomClient(auth as OAuth2PropertyValue);
const adminsResponse = await client.admins.list();
return {
options: adminsResponse.admins.map((c) => {
const res = { value: c.id, label: '' };
if (c.name) {
res.label = c.name;
} else if (c.email) {
res.label = c.email;
} else {
res.label = c.id;
}
return res;
}),
};
},
refreshers: [],
}),
contacts: <R extends boolean>(options: {
displayName: string;
required: R;
}) =>
Property.Dropdown<string, R, typeof intercomAuth>({
auth: intercomAuth,
displayName: options.displayName,
required: options.required,
options: async ({ auth }) => {
if (!auth) {
return {
options: [],
disabled: true,
placeholder: 'Please connect your account first',
};
}
const client = intercomClient(auth);
const contactsResponse = await client.contacts.list({});
return {
options: contactsResponse.data.map((c) => {
const res = { value: c.id, label: '' };
if (c.name) {
res.label = c.name;
} else if (c.email) {
res.label = c.email;
} else {
res.label = c.id;
}
return res;
}),
};
},
refreshers: [],
}),
};
export type Operator =
| '='
| '!='
| 'IN'
| 'NIN'
| '<'
| '>'
| '~'
| '!~'
| '^'
| '$';
export type TriggerPayload = {
type: string;
app_id: string;
id: string;
topic: string;
data: {
type: string;
item: Record<string, any>;
};
};

View File

@@ -0,0 +1,408 @@
import { AuthenticationType, httpClient, HttpMethod } from '@activepieces/pieces-common';
import { intercomClient } from '.';
import { intercomAuth } from '../../index';
import {
DropdownOption,
DynamicPropsValue,
PiecePropValueSchema,
Property,
} from '@activepieces/pieces-framework';
export const conversationIdProp = (displayName: string, required = true) =>
Property.Dropdown({
auth: intercomAuth,
displayName,
required,
refreshers: [],
options: async ({ auth }) => {
if (!auth) {
return {
options: [],
disabled: true,
placeholder: 'Please connect your account first.',
};
}
const authValue = auth as PiecePropValueSchema<typeof intercomAuth>;
const client = intercomClient(authValue);
const response = await client.conversations.list();
const options: DropdownOption<string>[] = [];
for await (const conversation of response) {
options.push({
value: conversation.id,
label: `${conversation.source.author.email}${
conversation.title ? `, ${conversation.title}` : ''
}, ${conversation.id}`,
});
}
return {
disabled: false,
options,
};
},
});
export const tagIdProp = (displayName: string, required = true) =>
Property.Dropdown({
auth: intercomAuth,
displayName,
required,
refreshers: [],
options: async ({ auth }) => {
if (!auth) {
return {
options: [],
disabled: true,
placeholder: 'Please connect your account first.',
};
}
const authValue = auth as PiecePropValueSchema<typeof intercomAuth>;
const client = intercomClient(authValue);
const response = await client.tags.list();
const options: DropdownOption<string>[] = [];
for (const tag of response.data) {
options.push({
value: tag.id,
label: tag.name,
});
}
return {
disabled: false,
options,
};
},
});
export const companyIdProp = (displayName: string, required = true) =>
Property.Dropdown({
auth: intercomAuth,
displayName,
required,
refreshers: [],
options: async ({ auth }) => {
if (!auth) {
return {
options: [],
disabled: true,
placeholder: 'Please connect your account first.',
};
}
const authValue = auth as PiecePropValueSchema<typeof intercomAuth>;
const client = intercomClient(authValue);
const response = await client.companies.list();
const options: DropdownOption<string>[] = [];
for await (const company of response) {
options.push({
value: company.id,
label: company.name,
});
}
return {
disabled: false,
options,
};
},
});
export const contactIdProp = (displayName: string, contactType: string | null, required = true) =>
Property.Dropdown({
auth: intercomAuth,
displayName,
required,
refreshers: [],
options: async ({ auth }) => {
if (!auth) {
return {
options: [],
disabled: true,
placeholder: 'Please connect your account first.',
};
}
const authValue = auth as PiecePropValueSchema<typeof intercomAuth>;
const client = intercomClient(authValue);
const response = await client.contacts.list();
const options: DropdownOption<string>[] = [];
for await (const contact of response) {
if (contactType === null || contact.role === contactType) {
options.push({
value: contact.id,
label: `${contact.name ?? ''}, ${contact.email}, ${contact.external_id ?? ''}`,
});
}
}
return {
disabled: false,
options,
};
},
});
export const collectionIdProp = (displayName: string, required = true) =>
Property.Dropdown({
auth: intercomAuth,
displayName,
required,
refreshers: [],
options: async ({ auth }) => {
if (!auth) {
return {
options: [],
disabled: true,
placeholder: 'Please connect your account first.',
};
}
const authValue = auth as PiecePropValueSchema<typeof intercomAuth>;
const client = intercomClient(authValue);
const response = await client.helpCenters.collections.list();
const options: DropdownOption<string>[] = [];
for await (const collection of response) {
options.push({
value: collection.id,
label: collection.name,
});
}
return {
disabled: false,
options,
};
},
});
export const ticketTypeIdProp = (displayName: string, required = true) =>
Property.Dropdown({
auth: intercomAuth,
displayName,
required,
refreshers: [],
options: async ({ auth }) => {
if (!auth) {
return {
options: [],
disabled: true,
placeholder: 'Please connect your account first.',
};
}
const authValue = auth as PiecePropValueSchema<typeof intercomAuth>;
const response = await httpClient.sendRequest<{ data: Array<{ id: string; name: string }> }>({
method: HttpMethod.GET,
url: `https://api.${authValue.props?.['region']}.io/ticket_types `,
authentication: {
type: AuthenticationType.BEARER_TOKEN,
token: authValue.access_token,
},
});
const options: DropdownOption<string>[] = [];
for (const type of response.body.data) {
options.push({
value: type.id,
label: type.name,
});
}
return {
disabled: false,
options,
};
},
});
export const ticketStateIdProp = (displayName: string, required = true) =>
Property.Dropdown({
auth: intercomAuth,
displayName,
required,
refreshers: [],
options: async ({ auth }) => {
if (!auth) {
return {
options: [],
disabled: true,
};
}
const authValue = auth as PiecePropValueSchema<typeof intercomAuth>;
const options: DropdownOption<string>[] = [];
const response = await httpClient.sendRequest<{
data: Array<{ id: string; internal_label: string }>;
}>({
method: HttpMethod.GET,
url: `https://api.${authValue.props?.['region']}.io/ticket_states`,
authentication: {
type: AuthenticationType.BEARER_TOKEN,
token: authValue.access_token,
},
});
if (response.body.data) {
for (const state of response.body.data) {
options.push({
label: state.internal_label,
value: state.id,
});
}
}
return {
disabled: true,
options: [],
};
},
});
export const ticketIdProp = (displayName: string, required = true) =>
Property.Dropdown({
auth: intercomAuth,
displayName,
required,
refreshers: ['ticketTypeId'],
options: async ({ auth, ticketTypeId }) => {
if (!auth || !ticketTypeId) {
return {
options: [],
disabled: true,
placeholder: 'Please connect your account first.',
};
}
const authValue = auth as PiecePropValueSchema<typeof intercomAuth>;
const client = intercomClient(authValue);
const options: DropdownOption<string>[] = [];
const response = await client.tickets.search({
query: {
field: 'ticket_type_id',
operator: '=',
value: ticketTypeId as unknown as string,
},
pagination: { per_page: 100 },
});
for await (const ticket of response) {
options.push({
value: ticket.id,
label: (ticket.ticket_attributes['_default_title_'] as string) ?? ticket.id,
});
}
return {
disabled: false,
options,
};
},
});
export const ticketPropertiesProp = (displayName: string, required = true) =>
Property.DynamicProperties({
auth: intercomAuth,
displayName,
refreshers: ['ticketTypeId'],
required,
props: async ({ auth, ticketTypeId }) => {
if (!auth) return {};
if (!ticketTypeId) return {};
const props: DynamicPropsValue = {};
const authValue = auth as PiecePropValueSchema<typeof intercomAuth>;
const response = await httpClient.sendRequest<{
ticket_type_attributes: {
data: Array<{ data_type: string; name: string; input_options: Record<string, unknown> }>;
};
}>({
method: HttpMethod.GET,
url: `https://api.${authValue.props?.['region']}.io/ticket_types/${ticketTypeId} `,
authentication: {
type: AuthenticationType.BEARER_TOKEN,
token: authValue.access_token,
},
});
for (const field of response.body.ticket_type_attributes.data) {
switch (field.data_type) {
case 'string':
props[field.name] = Property.LongText({
displayName:
field.name === '_default_title_'
? 'Title (Default)'
: field.name === '_default_description_'
? 'Description (Default)'
: field.name,
required: false,
});
break;
case 'integer':
case 'decimal':
props[field.name] = Property.Number({
displayName: field.name,
required: false,
});
break;
case 'boolean':
props[field.name] = Property.Checkbox({
displayName: field.name,
required: false,
});
break;
case 'datetime':
props[field.name] = Property.DateTime({
displayName: field.name,
required: false,
});
break;
case 'list':
{
const options = field.input_options.list_options as Array<{
label: string;
id: string;
}>;
props[field.name] = Property.StaticDropdown({
displayName: field.name,
required: false,
options: {
disabled: false,
options: options
? options.map((option) => ({
value: option.id,
label: option.label,
}))
: [],
},
});
}
break;
default:
break;
}
}
return props;
},
});

View File

@@ -0,0 +1,180 @@
import { createTrigger, TriggerStrategy } from '@activepieces/pieces-framework';
import { intercomAuth } from '../..';
import { intercomClient, TriggerPayload } from '../common';
export const contactRepliedTrigger = createTrigger({
name: 'contactReplied',
displayName: 'Contact Replied',
description: 'Triggers when a contact replies to a Conversation in Intercom.',
props: {},
auth: intercomAuth,
type: TriggerStrategy.APP_WEBHOOK,
async onEnable(context) {
const client = intercomClient(context.auth);
const response = await client.admins.identify();
if (!response.app?.id_code) {
throw new Error('Could not find admin id code');
}
context.app.createListeners({
events: ['conversation.user.replied'],
identifierValue: response['app']['id_code'],
});
},
async onDisable(context) {
// implement webhook deletion logic
},
async test(context) {
const client = intercomClient(context.auth);
const response = await client.conversations.list({ per_page: 10 });
return response.data;
},
async run(context) {
const payload = context.payload.body as TriggerPayload;
return [payload.data.item];
},
sampleData: {
type: 'conversation',
id: '2',
created_at: 1739105560,
updated_at: 1739524230,
waiting_since: null,
snoozed_until: null,
source: {
type: null,
id: '2',
delivered_as: 'admin_initiated',
subject: '',
body: '',
author: {
type: 'admin',
id: '8055721',
name: 'Fin',
email: 'operator+k2gbyfxu@intercom.io',
},
attachments: [],
url: null,
redacted: false,
},
contacts: {
type: 'contact.list',
contacts: [
{
type: 'contact',
id: '67a87380c16da6b56c76bbb7',
external_id: '1234567',
},
],
},
first_contact_reply: null,
admin_assignee_id: 8055717,
team_assignee_id: null,
open: true,
state: 'open',
read: false,
tags: {
type: 'tag.list',
tags: [],
},
priority: 'not_priority',
sla_applied: null,
statistics: {
type: 'conversation_statistics',
time_to_assignment: null,
time_to_admin_reply: null,
time_to_first_close: null,
time_to_last_close: null,
median_time_to_reply: null,
first_contact_reply_at: null,
first_assignment_at: null,
first_admin_reply_at: null,
first_close_at: null,
last_assignment_at: null,
last_assignment_admin_reply_at: null,
last_contact_reply_at: null,
last_admin_reply_at: null,
last_close_at: null,
last_closed_by_id: null,
count_reopens: 0,
count_assignments: 0,
count_conversation_parts: 9,
},
conversation_rating: null,
teammates: {
type: 'admin.list',
admins: [
{
type: 'admin',
id: '8055717',
},
],
},
title: null,
custom_attributes: {
'Copilot used': false,
'Ticket category': 'Customer ticket',
'Created by': 8055721,
},
topics: {
type: 'topic.list',
topics: [],
total_count: 0,
},
ticket: {
type: 'ticket',
id: 2,
url: 'https://app.intercom.com/a/apps/ahah/conversations/2',
custom_attributes: {
_default_title_: {
value: 'fdfdf',
type: 'string',
},
_default_description_: {
value: 'dfdfdf',
type: 'string',
},
List: {
value: null,
type: 'list',
},
Number: {
value: null,
type: 'integer',
},
decimal: {
value: null,
type: 'decimal',
},
bool: {
value: null,
type: 'boolean',
},
'date time': {
value: null,
type: 'datetime',
},
files: {
value: null,
type: 'files',
},
},
state: 'in_progress',
ticket_type: 'zapier',
ticket_type_description: '',
ticket_type_emoji: '🚨',
ticket_custom_state_admin_label: 'In progress',
ticket_custom_state_user_label: 'In progress',
},
linked_objects: {
type: 'list',
data: [],
total_count: 0,
has_more: false,
},
ai_agent: null,
ai_agent_participated: false,
},
});

View File

@@ -0,0 +1,160 @@
import { intercomAuth } from '../../index';
import { createTrigger, Property, TriggerStrategy } from '@activepieces/pieces-framework';
import { intercomClient, TriggerPayload } from '../common';
export const contactUpdatedTrigger = createTrigger({
auth: intercomAuth,
name: 'contact-updated',
displayName: 'Updated Contact',
description: 'Triggers when a contact is updated.',
props: {
type: Property.StaticDropdown({
displayName: 'Type',
required: true,
defaultValue: 'user',
options: {
disabled: false,
options: [
{ label: 'User', value: 'user' },
{ label: 'Lead', value: 'lead' },
],
},
}),
},
type: TriggerStrategy.APP_WEBHOOK,
async onEnable(context) {
const client = intercomClient(context.auth);
const response = await client.admins.identify();
if (!response.app?.id_code) {
throw new Error('Could not find admin id code');
}
const event = context.propsValue.type === 'user' ? 'contact.user.updated' : 'contact.lead.updated';
context.app.createListeners({
events: [event],
identifierValue: response['app']['id_code'],
});
},
async onDisable(context) {
// implement webhook deletion logic
},
async test(context) {
const client = intercomClient(context.auth);
const response = await client.contacts.search({
query:{
field:'role',
operator:'=',
value:context.propsValue.type
},
pagination:{per_page:5}
});
return response.data;
},
async run(context) {
const payload = context.payload.body as TriggerPayload;
return [payload.data.item];
},
sampleData: {
type: 'contact',
id: '67a9b9dfcc14109e073fbe19',
workspace_id: 'nzekhfwb',
external_id: '5b803f65-bcec-4198-b4f4-a0588454b537',
role: 'user',
email: 'john.doe@example.com',
phone: null,
name: 'John Doe',
avatar: null,
owner_id: null,
social_profiles: {
type: 'list',
data: [],
},
has_hard_bounced: false,
marked_email_as_spam: false,
unsubscribed_from_emails: false,
created_at: '2025-02-10T08:33:35.910+00:00',
updated_at: '2025-02-10T08:33:35.907+00:00',
signed_up_at: null,
last_seen_at: null,
last_replied_at: null,
last_contacted_at: null,
last_email_opened_at: null,
last_email_clicked_at: null,
language_override: null,
browser: null,
browser_version: null,
browser_language: null,
os: null,
location: {
type: 'location',
country: null,
region: null,
city: null,
country_code: null,
continent_code: null,
},
android_app_name: null,
android_app_version: null,
android_device: null,
android_os_version: null,
android_sdk_version: null,
android_last_seen_at: null,
ios_app_name: null,
ios_app_version: null,
ios_device: null,
ios_os_version: null,
ios_sdk_version: null,
ios_last_seen_at: null,
custom_attributes: {},
tags: {
type: 'list',
data: [],
url: '/contacts/67a9b9dfcc14109e073fbe19/tags',
total_count: 0,
has_more: false,
},
notes: {
type: 'list',
data: [],
url: '/contacts/67a9b9dfcc14109e073fbe19/notes',
total_count: 0,
has_more: false,
},
companies: {
type: 'list',
data: [],
url: '/contacts/67a9b9dfcc14109e073fbe19/companies',
total_count: 0,
has_more: false,
},
opted_out_subscription_types: {
type: 'list',
data: [],
url: '/contacts/67a9b9dfcc14109e073fbe19/subscriptions',
total_count: 0,
has_more: false,
},
opted_in_subscription_types: {
type: 'list',
data: [],
url: '/contacts/67a9b9dfcc14109e073fbe19/subscriptions',
total_count: 0,
has_more: false,
},
utm_campaign: null,
utm_content: null,
utm_medium: null,
utm_source: null,
utm_term: null,
referrer: null,
sms_consent: false,
unsubscribed_from_sms: false,
enabled_push_messaging: null,
},
});

View File

@@ -0,0 +1,32 @@
import { createTrigger, TriggerStrategy } from '@activepieces/pieces-framework';
import { intercomAuth } from '../..';
import { intercomClient } from '../common';
export const conversationAssigned = createTrigger({
name: 'conversationAssigned',
displayName: 'Conversation assigned to any Intercom admin',
description: 'Triggers when a conversation is assigned to an admin',
props: {},
sampleData: undefined,
auth: intercomAuth,
type: TriggerStrategy.APP_WEBHOOK,
async onEnable(context) {
const client = intercomClient(context.auth);
const response = await client.admins.identify();
if (!response.app?.id_code) {
throw new Error('Could not find admin id code');
}
context.app.createListeners({
events: ['conversation.admin.assigned'],
identifierValue: response['app']['id_code'],
});
},
async onDisable(context) {
// implement webhook deletion logic
},
async run(context) {
return [context.payload.body];
},
});

View File

@@ -0,0 +1,187 @@
import { createTrigger, TriggerStrategy } from '@activepieces/pieces-framework';
import { intercomAuth } from '../..';
import { intercomClient, TriggerPayload } from '../common';
export const conversationClosedTrigger = createTrigger({
name: 'conversationClosed',
displayName: 'Conversation Closed',
description: 'Triggers when a conversation is closed.',
props: {},
auth: intercomAuth,
type: TriggerStrategy.APP_WEBHOOK,
async onEnable(context) {
const client = intercomClient(context.auth);
const response = await client.admins.identify();
if (!response.app?.id_code) {
throw new Error('Could not find admin id code');
}
context.app.createListeners({
events: ['conversation.admin.closed'],
identifierValue: response['app']['id_code'],
});
},
async onDisable(context) {
// implement webhook deletion logic
},
async test(context) {
const client = intercomClient(context.auth);
const response = await client.conversations.search({
query: {
field: 'state',
operator: '=',
value: 'closed',
},
pagination: { per_page: 5 },
});
return response.data;
},
async run(context) {
const payload = context.payload.body as TriggerPayload;
return [payload.data.item];
},
sampleData: {
type: 'conversation',
id: '2',
created_at: 1739105560,
updated_at: 1739524230,
waiting_since: null,
snoozed_until: null,
source: {
type: null,
id: '2',
delivered_as: 'admin_initiated',
subject: '',
body: '',
author: {
type: 'admin',
id: '8055721',
name: 'Fin',
email: 'operator+k2gbyfxu@intercom.io',
},
attachments: [],
url: null,
redacted: false,
},
contacts: {
type: 'contact.list',
contacts: [
{
type: 'contact',
id: '67a87380c16da6b56c76bbb7',
external_id: '1234567',
},
],
},
first_contact_reply: null,
admin_assignee_id: 8055717,
team_assignee_id: null,
open: true,
state: 'closed',
read: false,
tags: {
type: 'tag.list',
tags: [],
},
priority: 'not_priority',
sla_applied: null,
statistics: {
type: 'conversation_statistics',
time_to_assignment: null,
time_to_admin_reply: null,
time_to_first_close: null,
time_to_last_close: null,
median_time_to_reply: null,
first_contact_reply_at: null,
first_assignment_at: null,
first_admin_reply_at: null,
first_close_at: null,
last_assignment_at: null,
last_assignment_admin_reply_at: null,
last_contact_reply_at: null,
last_admin_reply_at: null,
last_close_at: null,
last_closed_by_id: null,
count_reopens: 0,
count_assignments: 0,
count_conversation_parts: 9,
},
conversation_rating: null,
teammates: {
type: 'admin.list',
admins: [
{
type: 'admin',
id: '8055717',
},
],
},
title: null,
custom_attributes: {
'Copilot used': false,
'Ticket category': 'Customer ticket',
'Created by': 8055721,
},
topics: {
type: 'topic.list',
topics: [],
total_count: 0,
},
ticket: {
type: 'ticket',
id: 2,
url: 'https://app.intercom.com/a/apps/ahah/conversations/2',
custom_attributes: {
_default_title_: {
value: 'fdfdf',
type: 'string',
},
_default_description_: {
value: 'dfdfdf',
type: 'string',
},
List: {
value: null,
type: 'list',
},
Number: {
value: null,
type: 'integer',
},
decimal: {
value: null,
type: 'decimal',
},
bool: {
value: null,
type: 'boolean',
},
'date time': {
value: null,
type: 'datetime',
},
files: {
value: null,
type: 'files',
},
},
state: 'closed',
ticket_type: 'zapier',
ticket_type_description: '',
ticket_type_emoji: '🚨',
ticket_custom_state_admin_label: 'In progress',
ticket_custom_state_user_label: 'In progress',
},
linked_objects: {
type: 'list',
data: [],
total_count: 0,
has_more: false,
},
ai_agent: null,
ai_agent_participated: false,
},
});

View File

@@ -0,0 +1,54 @@
import {
createTrigger,
TriggerStrategy,
} from '@activepieces/pieces-framework';
import { intercomAuth } from '../..';
import { intercomClient } from '../common';
import { tagIdProp } from '../common/props';
export const conversationPartTagged = createTrigger({
name: 'conversationPartTagged',
displayName: 'Tag added to a conversation part',
description: 'Triggers when a conversation part is tagged.',
props: {
tagId: tagIdProp('Tag', false),
},
auth: intercomAuth,
type: TriggerStrategy.APP_WEBHOOK,
async onEnable(context) {
const client = intercomClient(context.auth);
const response = await client.admins.identify();
if (!response.app?.id_code) {
throw new Error('Could not find admin id code');
}
context.app.createListeners({
events: ['conversation_part.tag.created'],
identifierValue: response['app']['id_code'],
});
},
async onDisable(context) {
// implement webhook deletion logic
},
async run(context) {
const tag = context.propsValue.tagId;
const payloadBody = context.payload.body as IntercomPayloadBodyType;
if (!tag || payloadBody?.data?.item?.tag.id === tag) {
return [payloadBody.data.item];
}
return [];
},
sampleData: undefined
});
type IntercomPayloadBodyType = {
data: {
item: {
tag: {
id: string;
};
};
};
};

View File

@@ -0,0 +1,180 @@
import { createTrigger, TriggerStrategy } from '@activepieces/pieces-framework';
import { intercomAuth } from '../..';
import { intercomClient, TriggerPayload } from '../common';
export const conversationRated = createTrigger({
name: 'conversationRated',
displayName: 'Conversation was rated',
description: 'Triggers when a conversation is rated',
props: {},
auth: intercomAuth,
type: TriggerStrategy.APP_WEBHOOK,
async onEnable(context) {
const client = intercomClient(context.auth);
const response = await client.admins.identify();
if (!response.app?.id_code) {
throw new Error('Could not find admin id code');
}
context.app.createListeners({
events: ['conversation.rating.added'],
identifierValue: response['app']['id_code'],
});
},
async onDisable(context) {
// implement webhook deletion logic
},
async test(context) {
const client = intercomClient(context.auth);
const response = await client.conversations.list({ per_page: 10 });
return response.data;
},
async run(context) {
const payload = context.payload.body as TriggerPayload;
return [payload.data.item];
},
sampleData: {
type: 'conversation',
id: '2',
created_at: 1739105560,
updated_at: 1739524230,
waiting_since: null,
snoozed_until: null,
source: {
type: null,
id: '2',
delivered_as: 'admin_initiated',
subject: '',
body: '',
author: {
type: 'admin',
id: '8055721',
name: 'Fin',
email: 'operator+k2gbyfxu@intercom.io',
},
attachments: [],
url: null,
redacted: false,
},
contacts: {
type: 'contact.list',
contacts: [
{
type: 'contact',
id: '67a87380c16da6b56c76bbb7',
external_id: '1234567',
},
],
},
first_contact_reply: null,
admin_assignee_id: 8055717,
team_assignee_id: null,
open: true,
state: 'open',
read: false,
tags: {
type: 'tag.list',
tags: [],
},
priority: 'not_priority',
sla_applied: null,
statistics: {
type: 'conversation_statistics',
time_to_assignment: null,
time_to_admin_reply: null,
time_to_first_close: null,
time_to_last_close: null,
median_time_to_reply: null,
first_contact_reply_at: null,
first_assignment_at: null,
first_admin_reply_at: null,
first_close_at: null,
last_assignment_at: null,
last_assignment_admin_reply_at: null,
last_contact_reply_at: null,
last_admin_reply_at: null,
last_close_at: null,
last_closed_by_id: null,
count_reopens: 0,
count_assignments: 0,
count_conversation_parts: 9,
},
conversation_rating: null,
teammates: {
type: 'admin.list',
admins: [
{
type: 'admin',
id: '8055717',
},
],
},
title: null,
custom_attributes: {
'Copilot used': false,
'Ticket category': 'Customer ticket',
'Created by': 8055721,
},
topics: {
type: 'topic.list',
topics: [],
total_count: 0,
},
ticket: {
type: 'ticket',
id: 2,
url: 'https://app.intercom.com/a/apps/ahah/conversations/2',
custom_attributes: {
_default_title_: {
value: 'fdfdf',
type: 'string',
},
_default_description_: {
value: 'dfdfdf',
type: 'string',
},
List: {
value: null,
type: 'list',
},
Number: {
value: null,
type: 'integer',
},
decimal: {
value: null,
type: 'decimal',
},
bool: {
value: null,
type: 'boolean',
},
'date time': {
value: null,
type: 'datetime',
},
files: {
value: null,
type: 'files',
},
},
state: 'in_progress',
ticket_type: 'zapier',
ticket_type_description: '',
ticket_type_emoji: '🚨',
ticket_custom_state_admin_label: 'In progress',
ticket_custom_state_user_label: 'In progress',
},
linked_objects: {
type: 'list',
data: [],
total_count: 0,
has_more: false,
},
ai_agent: null,
ai_agent_participated: false,
},
});

View File

@@ -0,0 +1,33 @@
import { createTrigger, TriggerStrategy } from '@activepieces/pieces-framework';
import { intercomAuth } from '../..';
import { intercomClient } from '../common';
export const conversationSnoozed = createTrigger({
// auth: check https://www.activepieces.com/docs/developers/piece-reference/authentication,
name: 'conversationSnoozed',
displayName: 'Conversation snoozed',
description: 'Triggers when a conversation is snoozed',
props: {},
sampleData: undefined,
auth: intercomAuth,
type: TriggerStrategy.APP_WEBHOOK,
async onEnable(context) {
const client = intercomClient(context.auth);
const response = await client.admins.identify();
if (!response.app?.id_code) {
throw new Error('Could not find admin id code');
}
context.app.createListeners({
events: ['conversation.admin.snoozed'],
identifierValue: response['app']['id_code'],
});
},
async onDisable(context) {
// implement webhook deletion logic
},
async run(context) {
return [context.payload.body];
},
});

View File

@@ -0,0 +1,33 @@
import { createTrigger, TriggerStrategy } from '@activepieces/pieces-framework';
import { intercomAuth } from '../..';
import { intercomClient } from '../common';
export const conversationUnsnoozed = createTrigger({
// auth: check https://www.activepieces.com/docs/developers/piece-reference/authentication,
name: 'conversationUnsnoozed',
displayName: 'Conversation unsnoozed',
description: 'Triggers when a conversation is unsnoozed',
props: {},
sampleData: undefined,
auth: intercomAuth,
type: TriggerStrategy.APP_WEBHOOK,
async onEnable(context) {
const client = intercomClient(context.auth);
const response = await client.admins.identify();
if (!response.app?.id_code) {
throw new Error('Could not find admin id code');
}
context.app.createListeners({
events: ['conversation.admin.unsnoozed'],
identifierValue: response['app']['id_code'],
});
},
async onDisable(context) {
// implement webhook deletion logic
},
async run(context) {
return [context.payload.body];
},
});

View File

@@ -0,0 +1,143 @@
import { intercomAuth } from '../../index';
import { createTrigger, TriggerStrategy } from '@activepieces/pieces-framework';
import { intercomClient, TriggerPayload } from '../common';
export const leadAddedEmailTrigger = createTrigger({
auth: intercomAuth,
name: 'lead-added-email',
displayName: 'Lead Added Email',
description: 'Triggers when a lead enters an email address.',
props: {},
type: TriggerStrategy.APP_WEBHOOK,
async onEnable(context) {
const client = intercomClient(context.auth);
const response = await client.admins.identify();
if (!response.app?.id_code) {
throw new Error('Could not find admin id code');
}
context.app.createListeners({
events: ['contact.lead.added_email'],
identifierValue: response['app']['id_code'],
});
},
async onDisable(context) {
// implement webhook deletion logic
},
async test(context) {
const client = intercomClient(context.auth);
const response = await client.contacts.search({
query: {
field: 'role',
operator: '=',
value: 'lead',
},
pagination: { per_page: 5 },
});
return response.data;
},
async run(context) {
const payload = context.payload.body as TriggerPayload;
return [payload.data.item];
},
sampleData: {
type: 'contact',
id: '67a9b9dfcc14109e073fbe19',
workspace_id: 'nzekhfwb',
external_id: '5b803f65-bcec-4198-b4f4-a0588454b537',
role: 'lead',
email: 'john.doe@example.com',
phone: null,
name: 'John Doe',
avatar: null,
owner_id: null,
social_profiles: {
type: 'list',
data: [],
},
has_hard_bounced: false,
marked_email_as_spam: false,
unsubscribed_from_emails: false,
created_at: '2025-02-10T08:33:35.910+00:00',
updated_at: '2025-02-10T08:33:35.907+00:00',
signed_up_at: null,
last_seen_at: null,
last_replied_at: null,
last_contacted_at: null,
last_email_opened_at: null,
last_email_clicked_at: null,
language_override: null,
browser: null,
browser_version: null,
browser_language: null,
os: null,
location: {
type: 'location',
country: null,
region: null,
city: null,
country_code: null,
continent_code: null,
},
android_app_name: null,
android_app_version: null,
android_device: null,
android_os_version: null,
android_sdk_version: null,
android_last_seen_at: null,
ios_app_name: null,
ios_app_version: null,
ios_device: null,
ios_os_version: null,
ios_sdk_version: null,
ios_last_seen_at: null,
custom_attributes: {},
tags: {
type: 'list',
data: [],
url: '/contacts/67a9b9dfcc14109e073fbe19/tags',
total_count: 0,
has_more: false,
},
notes: {
type: 'list',
data: [],
url: '/contacts/67a9b9dfcc14109e073fbe19/notes',
total_count: 0,
has_more: false,
},
companies: {
type: 'list',
data: [],
url: '/contacts/67a9b9dfcc14109e073fbe19/companies',
total_count: 0,
has_more: false,
},
opted_out_subscription_types: {
type: 'list',
data: [],
url: '/contacts/67a9b9dfcc14109e073fbe19/subscriptions',
total_count: 0,
has_more: false,
},
opted_in_subscription_types: {
type: 'list',
data: [],
url: '/contacts/67a9b9dfcc14109e073fbe19/subscriptions',
total_count: 0,
has_more: false,
},
utm_campaign: null,
utm_content: null,
utm_medium: null,
utm_source: null,
utm_term: null,
referrer: null,
sms_consent: false,
unsubscribed_from_sms: false,
enabled_push_messaging: null,
},
});

View File

@@ -0,0 +1,144 @@
import { intercomAuth } from '../../index';
import { createTrigger, TriggerStrategy } from '@activepieces/pieces-framework';
import { intercomClient, TriggerPayload } from '../common';
export const leadConvertedToUserTrigger = createTrigger({
auth: intercomAuth,
name: 'lead-converted-to-user',
displayName: 'Lead Converted To User',
description: 'Triggers when a lead is converted to a user.',
props: {},
type: TriggerStrategy.APP_WEBHOOK,
async onEnable(context) {
const client = intercomClient(context.auth);
const response = await client.admins.identify();
if (!response.app?.id_code) {
throw new Error('Could not find admin id code');
}
context.app.createListeners({
events: ['contact.merged'],
identifierValue: response['app']['id_code'],
});
},
async onDisable(context) {
// implement webhook deletion logic
},
async test(context) {
const client = intercomClient(context.auth);
const response = await client.contacts.search({
query:{
field:'role',
operator:'=',
value:'user'
},
pagination:{per_page:5}
});
return response.data;
},
async run(context) {
const payload = context.payload.body as TriggerPayload;
return [payload.data.item];
},
sampleData: {
type: 'contact',
id: '67a9b9dfcc14109e073fbe19',
workspace_id: 'nzekhfwb',
external_id: '5b803f65-bcec-4198-b4f4-a0588454b537',
role: 'user',
email: 'john.doe@example.com',
phone: null,
name: 'John Doe',
avatar: null,
owner_id: null,
social_profiles: {
type: 'list',
data: [],
},
has_hard_bounced: false,
marked_email_as_spam: false,
unsubscribed_from_emails: false,
created_at: '2025-02-10T08:33:35.910+00:00',
updated_at: '2025-02-10T08:33:35.907+00:00',
signed_up_at: null,
last_seen_at: null,
last_replied_at: null,
last_contacted_at: null,
last_email_opened_at: null,
last_email_clicked_at: null,
language_override: null,
browser: null,
browser_version: null,
browser_language: null,
os: null,
location: {
type: 'location',
country: null,
region: null,
city: null,
country_code: null,
continent_code: null,
},
android_app_name: null,
android_app_version: null,
android_device: null,
android_os_version: null,
android_sdk_version: null,
android_last_seen_at: null,
ios_app_name: null,
ios_app_version: null,
ios_device: null,
ios_os_version: null,
ios_sdk_version: null,
ios_last_seen_at: null,
custom_attributes: {},
tags: {
type: 'list',
data: [],
url: '/contacts/67a9b9dfcc14109e073fbe19/tags',
total_count: 0,
has_more: false,
},
notes: {
type: 'list',
data: [],
url: '/contacts/67a9b9dfcc14109e073fbe19/notes',
total_count: 0,
has_more: false,
},
companies: {
type: 'list',
data: [],
url: '/contacts/67a9b9dfcc14109e073fbe19/companies',
total_count: 0,
has_more: false,
},
opted_out_subscription_types: {
type: 'list',
data: [],
url: '/contacts/67a9b9dfcc14109e073fbe19/subscriptions',
total_count: 0,
has_more: false,
},
opted_in_subscription_types: {
type: 'list',
data: [],
url: '/contacts/67a9b9dfcc14109e073fbe19/subscriptions',
total_count: 0,
has_more: false,
},
utm_campaign: null,
utm_content: null,
utm_medium: null,
utm_source: null,
utm_term: null,
referrer: null,
sms_consent: false,
unsubscribed_from_sms: false,
enabled_push_messaging: null,
},
});

View File

@@ -0,0 +1,136 @@
import { intercomAuth } from '../../index';
import { createTrigger, TriggerStrategy } from '@activepieces/pieces-framework';
import { intercomClient, TriggerPayload } from '../common';
export const newCompanyTrigger = createTrigger({
auth: intercomAuth,
name: 'new-company',
displayName: 'New Company',
description: 'Triggers when a new company is created.',
props: {},
type: TriggerStrategy.APP_WEBHOOK,
async onEnable(context) {
const client = intercomClient(context.auth);
const response = await client.admins.identify();
if (!response.app?.id_code) {
throw new Error('Could not find admin id code');
}
context.app.createListeners({
events: ['company.created'],
identifierValue: response['app']['id_code'],
});
},
async onDisable(context) {
// implement webhook deletion logic
},
async test(context) {
const client = intercomClient(context.auth);
const response = await client.companies.list({ per_page: 5 });
return response.data;
},
async run(context) {
const payload = context.payload.body as TriggerPayload;
return [payload.data.item];
},
sampleData: {
type: 'contact',
id: '67a9b9dfcc14109e073fbe19',
workspace_id: 'nzekhfwb',
external_id: '5b803f65-bcec-4198-b4f4-a0588454b537',
role: 'lead',
email: 'john.doe@example.com',
phone: null,
name: 'John Doe',
avatar: null,
owner_id: null,
social_profiles: {
type: 'list',
data: [],
},
has_hard_bounced: false,
marked_email_as_spam: false,
unsubscribed_from_emails: false,
created_at: '2025-02-10T08:33:35.910+00:00',
updated_at: '2025-02-10T08:33:35.907+00:00',
signed_up_at: null,
last_seen_at: null,
last_replied_at: null,
last_contacted_at: null,
last_email_opened_at: null,
last_email_clicked_at: null,
language_override: null,
browser: null,
browser_version: null,
browser_language: null,
os: null,
location: {
type: 'location',
country: null,
region: null,
city: null,
country_code: null,
continent_code: null,
},
android_app_name: null,
android_app_version: null,
android_device: null,
android_os_version: null,
android_sdk_version: null,
android_last_seen_at: null,
ios_app_name: null,
ios_app_version: null,
ios_device: null,
ios_os_version: null,
ios_sdk_version: null,
ios_last_seen_at: null,
custom_attributes: {},
tags: {
type: 'list',
data: [],
url: '/contacts/67a9b9dfcc14109e073fbe19/tags',
total_count: 0,
has_more: false,
},
notes: {
type: 'list',
data: [],
url: '/contacts/67a9b9dfcc14109e073fbe19/notes',
total_count: 0,
has_more: false,
},
companies: {
type: 'list',
data: [],
url: '/contacts/67a9b9dfcc14109e073fbe19/companies',
total_count: 0,
has_more: false,
},
opted_out_subscription_types: {
type: 'list',
data: [],
url: '/contacts/67a9b9dfcc14109e073fbe19/subscriptions',
total_count: 0,
has_more: false,
},
opted_in_subscription_types: {
type: 'list',
data: [],
url: '/contacts/67a9b9dfcc14109e073fbe19/subscriptions',
total_count: 0,
has_more: false,
},
utm_campaign: null,
utm_content: null,
utm_medium: null,
utm_source: null,
utm_term: null,
referrer: null,
sms_consent: false,
unsubscribed_from_sms: false,
enabled_push_messaging: null,
},
});

View File

@@ -0,0 +1,180 @@
import { createTrigger, TriggerStrategy } from '@activepieces/pieces-framework';
import { intercomAuth } from '../..';
import { intercomClient, TriggerPayload } from '../common';
export const newConversationFromUser = createTrigger({
name: 'newConversationFromUser',
displayName: 'New Conversation',
description: 'Triggers when a conversation is created by a user or lead (not an admin).',
props: {},
auth: intercomAuth,
type: TriggerStrategy.APP_WEBHOOK,
async onEnable(context) {
const client = intercomClient(context.auth);
const response = await client.admins.identify();
if (!response.app?.id_code) {
throw new Error('Could not find admin id code');
}
context.app.createListeners({
events: ['conversation.user.created'],
identifierValue: response['app']['id_code'],
});
},
async onDisable(context) {
// implement webhook deletion logic
},
async test(context) {
const client = intercomClient(context.auth);
const response = await client.conversations.list({ per_page: 10 });
return response.data;
},
async run(context) {
const payload = context.payload.body as TriggerPayload;
return [payload.data.item];
},
sampleData: {
type: 'conversation',
id: '2',
created_at: 1739105560,
updated_at: 1739524230,
waiting_since: null,
snoozed_until: null,
source: {
type: null,
id: '2',
delivered_as: 'admin_initiated',
subject: '',
body: '',
author: {
type: 'admin',
id: '8055721',
name: 'Fin',
email: 'operator+k2gbyfxu@intercom.io',
},
attachments: [],
url: null,
redacted: false,
},
contacts: {
type: 'contact.list',
contacts: [
{
type: 'contact',
id: '67a87380c16da6b56c76bbb7',
external_id: '1234567',
},
],
},
first_contact_reply: null,
admin_assignee_id: 8055717,
team_assignee_id: null,
open: true,
state: 'open',
read: false,
tags: {
type: 'tag.list',
tags: [],
},
priority: 'not_priority',
sla_applied: null,
statistics: {
type: 'conversation_statistics',
time_to_assignment: null,
time_to_admin_reply: null,
time_to_first_close: null,
time_to_last_close: null,
median_time_to_reply: null,
first_contact_reply_at: null,
first_assignment_at: null,
first_admin_reply_at: null,
first_close_at: null,
last_assignment_at: null,
last_assignment_admin_reply_at: null,
last_contact_reply_at: null,
last_admin_reply_at: null,
last_close_at: null,
last_closed_by_id: null,
count_reopens: 0,
count_assignments: 0,
count_conversation_parts: 9,
},
conversation_rating: null,
teammates: {
type: 'admin.list',
admins: [
{
type: 'admin',
id: '8055717',
},
],
},
title: null,
custom_attributes: {
'Copilot used': false,
'Ticket category': 'Customer ticket',
'Created by': 8055721,
},
topics: {
type: 'topic.list',
topics: [],
total_count: 0,
},
ticket: {
type: 'ticket',
id: 2,
url: 'https://app.intercom.com/a/apps/ahah/conversations/2',
custom_attributes: {
_default_title_: {
value: 'fdfdf',
type: 'string',
},
_default_description_: {
value: 'dfdfdf',
type: 'string',
},
List: {
value: null,
type: 'list',
},
Number: {
value: null,
type: 'integer',
},
decimal: {
value: null,
type: 'decimal',
},
bool: {
value: null,
type: 'boolean',
},
'date time': {
value: null,
type: 'datetime',
},
files: {
value: null,
type: 'files',
},
},
state: 'in_progress',
ticket_type: 'zapier',
ticket_type_description: '',
ticket_type_emoji: '🚨',
ticket_custom_state_admin_label: 'In progress',
ticket_custom_state_user_label: 'In progress',
},
linked_objects: {
type: 'list',
data: [],
total_count: 0,
has_more: false,
},
ai_agent: null,
ai_agent_participated: false,
},
});

View File

@@ -0,0 +1,143 @@
import { intercomAuth } from '../../index';
import { createTrigger, TriggerStrategy } from '@activepieces/pieces-framework';
import { intercomClient, TriggerPayload } from '../common';
export const newLeadTrigger = createTrigger({
auth: intercomAuth,
name: 'new-lead',
displayName: 'New Lead',
description: 'Triggers when a new lead is created.',
props: {},
type: TriggerStrategy.APP_WEBHOOK,
async onEnable(context) {
const client = intercomClient(context.auth);
const response = await client.admins.identify();
if (!response.app?.id_code) {
throw new Error('Could not find admin id code');
}
context.app.createListeners({
events: ['contact.lead.created'],
identifierValue: response['app']['id_code'],
});
},
async onDisable(context) {
// implement webhook deletion logic
},
async test(context) {
const client = intercomClient(context.auth);
const response = await client.contacts.search({
query: {
field: 'role',
operator: '=',
value: 'lead',
},
pagination: { per_page: 5 },
});
return response.data;
},
async run(context) {
const payload = context.payload.body as TriggerPayload;
return [payload.data.item];
},
sampleData: {
type: 'contact',
id: '67a9b9dfcc14109e073fbe19',
workspace_id: 'nzekhfwb',
external_id: '5b803f65-bcec-4198-b4f4-a0588454b537',
role: 'lead',
email: 'john.doe@example.com',
phone: null,
name: 'John Doe',
avatar: null,
owner_id: null,
social_profiles: {
type: 'list',
data: [],
},
has_hard_bounced: false,
marked_email_as_spam: false,
unsubscribed_from_emails: false,
created_at: '2025-02-10T08:33:35.910+00:00',
updated_at: '2025-02-10T08:33:35.907+00:00',
signed_up_at: null,
last_seen_at: null,
last_replied_at: null,
last_contacted_at: null,
last_email_opened_at: null,
last_email_clicked_at: null,
language_override: null,
browser: null,
browser_version: null,
browser_language: null,
os: null,
location: {
type: 'location',
country: null,
region: null,
city: null,
country_code: null,
continent_code: null,
},
android_app_name: null,
android_app_version: null,
android_device: null,
android_os_version: null,
android_sdk_version: null,
android_last_seen_at: null,
ios_app_name: null,
ios_app_version: null,
ios_device: null,
ios_os_version: null,
ios_sdk_version: null,
ios_last_seen_at: null,
custom_attributes: {},
tags: {
type: 'list',
data: [],
url: '/contacts/67a9b9dfcc14109e073fbe19/tags',
total_count: 0,
has_more: false,
},
notes: {
type: 'list',
data: [],
url: '/contacts/67a9b9dfcc14109e073fbe19/notes',
total_count: 0,
has_more: false,
},
companies: {
type: 'list',
data: [],
url: '/contacts/67a9b9dfcc14109e073fbe19/companies',
total_count: 0,
has_more: false,
},
opted_out_subscription_types: {
type: 'list',
data: [],
url: '/contacts/67a9b9dfcc14109e073fbe19/subscriptions',
total_count: 0,
has_more: false,
},
opted_in_subscription_types: {
type: 'list',
data: [],
url: '/contacts/67a9b9dfcc14109e073fbe19/subscriptions',
total_count: 0,
has_more: false,
},
utm_campaign: null,
utm_content: null,
utm_medium: null,
utm_source: null,
utm_term: null,
referrer: null,
sms_consent: false,
unsubscribed_from_sms: false,
enabled_push_messaging: null,
},
});

View File

@@ -0,0 +1,284 @@
import { intercomAuth } from '../../index';
import { createTrigger, TriggerStrategy } from '@activepieces/pieces-framework';
import { intercomClient, TriggerPayload } from '../common';
export const newTicketTrigger = createTrigger({
auth: intercomAuth,
name: 'new-ticket',
displayName: 'New Ticket',
description: 'Triggers when a new ticket is created.',
props: {},
type: TriggerStrategy.APP_WEBHOOK,
async onEnable(context) {
const client = intercomClient(context.auth);
const response = await client.admins.identify();
if (!response.app?.id_code) {
throw new Error('Could not find admin id code');
}
context.app.createListeners({
events: ['ticket.created'],
identifierValue: response['app']['id_code'],
});
},
async onDisable(context) {
// implement webhook deletion logic
},
async test(context) {
const client = intercomClient(context.auth);
const response = await client.tickets.search({
query: {
field: 'open',
operator: '=',
value: 'true',
},
pagination: { per_page: 5 },
});
return response.data;
},
async run(context) {
const payload = context.payload.body as TriggerPayload;
return [payload.data.item];
},
sampleData: {
type: 'ticket',
id: '2',
ticket_id: '1',
ticket_attributes: {
_default_title_: 'fdfdf',
_default_description_: 'dfdfdf',
List: null,
Number: null,
decimal: null,
bool: null,
'date time': null,
files: [],
},
ticket_state: 'in_progress',
ticket_type: {
type: 'ticket_type',
id: '1',
name: 'test',
description: '',
icon: '🚨',
workspace_id: 'nzekhfwb',
archived: false,
created_at: 1739105534,
updated_at: 1739105534,
is_internal: false,
ticket_type_attributes: {
type: 'list',
data: [
{
type: 'ticket_type_attribute',
id: '6615713',
workspace_id: 'nzekhfwb',
name: '_default_title_',
description: '',
data_type: 'string',
input_options: {
multiline: false,
},
order: 0,
required_to_create: false,
required_to_create_for_contacts: false,
visible_on_create: true,
visible_to_contacts: true,
default: true,
ticket_type_id: 1,
archived: false,
created_at: 1739105534,
updated_at: 1739105534,
},
{
type: 'ticket_type_attribute',
id: '6615714',
workspace_id: 'nzekhfwb',
name: '_default_description_',
description: '',
data_type: 'string',
input_options: {
multiline: true,
},
order: 1,
required_to_create: false,
required_to_create_for_contacts: false,
visible_on_create: true,
visible_to_contacts: true,
default: true,
ticket_type_id: 1,
archived: false,
created_at: 1739105534,
updated_at: 1739105534,
},
],
},
category: 'Customer',
},
contacts: {
type: 'contact.list',
contacts: [
{
type: 'contact',
id: '67a87380c16da6b56c76bbb7',
external_id: '1234567',
},
],
},
admin_assignee_id: '8055717',
team_assignee_id: '0',
created_at: 1739105560,
updated_at: 1739524230,
ticket_parts: {
type: 'ticket_part.list',
ticket_parts: [
{
type: 'ticket_part',
id: '3',
part_type: 'ticket_state_updated_by_admin',
ticket_state: 'submitted',
previous_ticket_state: 'submitted',
created_at: 1739105561,
updated_at: 1739105561,
author: {
id: '8055721',
type: 'bot',
name: 'Fin',
email: 'operator+k2gbyfxu@intercom.io',
},
attachments: [],
redacted: false,
},
{
type: 'ticket_part',
id: '5',
part_type: 'assignment',
body: '<p class="no-margin">hghh</p>',
created_at: 1739109004,
updated_at: 1739111399,
assigned_to: {
type: 'admin',
id: '8055717',
},
author: {
id: '8055717',
type: 'admin',
name: 'John Doe',
email: 'johndoe@gmail.com',
},
attachments: [],
redacted: false,
},
{
type: 'ticket_part',
id: '6',
part_type: 'conversation_tags_updated',
created_at: 1739109007,
updated_at: 1739109007,
author: {
id: '8055717',
type: 'admin',
name: 'John Doe',
email: 'johndoe@gmail.com',
},
attachments: [],
redacted: false,
},
{
type: 'ticket_part',
id: '7',
part_type: 'conversation_tags_updated',
created_at: 1739109008,
updated_at: 1739109008,
author: {
id: '8055717',
type: 'admin',
name: 'John Doe',
email: 'johndoe@gmail.com',
},
attachments: [],
redacted: false,
},
{
type: 'ticket_part',
id: '14',
part_type: 'conversation_tags_updated',
created_at: 1739111399,
updated_at: 1739111399,
author: {
id: '8055717',
type: 'admin',
name: 'John Doe',
email: 'johndoe@gmail.com',
},
attachments: [],
redacted: false,
},
{
type: 'ticket_part',
id: '15',
part_type: 'conversation_tags_updated',
created_at: 1739111400,
updated_at: 1739111400,
author: {
id: '8055717',
type: 'admin',
name: 'John Doe',
email: 'johndoe@gmail.com',
},
attachments: [],
redacted: false,
},
{
type: 'ticket_part',
id: '16',
part_type: 'comment',
body: '<p class="no-margin">ss</p>',
created_at: 1739111407,
updated_at: 1739111407,
author: {
id: '8055717',
type: 'admin',
name: 'John Doe',
email: 'johndoe@gmail.com',
},
attachments: [],
redacted: false,
},
{
type: 'ticket_part',
id: '37',
part_type: 'ticket_state_updated_by_admin',
ticket_state: 'in_progress',
previous_ticket_state: 'submitted',
created_at: 1739524230,
updated_at: 1739524230,
author: {
id: '8055717',
type: 'admin',
name: 'John Doe',
email: 'johndoe@gmail.com',
},
attachments: [],
redacted: false,
},
],
total_count: 8,
},
open: true,
linked_objects: {
type: 'list',
data: [],
total_count: 0,
has_more: false,
},
category: 'Customer',
is_shared: true,
company_id: '67a8a24c4670c9f1995b2382',
ticket_state_internal_label: 'In progress',
ticket_state_external_label: 'In progress',
},
});

View File

@@ -0,0 +1,143 @@
import { intercomAuth } from '../../index';
import { createTrigger, TriggerStrategy } from '@activepieces/pieces-framework';
import { intercomClient, TriggerPayload } from '../common';
export const newUserTrigger = createTrigger({
auth: intercomAuth,
name: 'new-user',
displayName: 'New User',
description: 'Triggers when a new user is created.',
props: {},
type: TriggerStrategy.APP_WEBHOOK,
async onEnable(context) {
const client = intercomClient(context.auth);
const response = await client.admins.identify();
if (!response.app?.id_code) {
throw new Error('Could not find admin id code');
}
context.app.createListeners({
events: ['contact.user.created'],
identifierValue: response['app']['id_code'],
});
},
async onDisable(context) {
// implement webhook deletion logic
},
async test(context) {
const client = intercomClient(context.auth);
const response = await client.contacts.search({
query: {
field: 'role',
operator: '=',
value: 'user',
},
pagination: { per_page: 5 },
});
return response.data;
},
async run(context) {
const payload = context.payload.body as TriggerPayload;
return [payload.data.item];
},
sampleData: {
type: 'contact',
id: '67a9b9dfcc14109e073fbe19',
workspace_id: 'nzekhfwb',
external_id: '5b803f65-bcec-4198-b4f4-a0588454b537',
role: 'user',
email: 'john.doe@example.com',
phone: null,
name: 'John Doe',
avatar: null,
owner_id: null,
social_profiles: {
type: 'list',
data: [],
},
has_hard_bounced: false,
marked_email_as_spam: false,
unsubscribed_from_emails: false,
created_at: '2025-02-10T08:33:35.910+00:00',
updated_at: '2025-02-10T08:33:35.907+00:00',
signed_up_at: null,
last_seen_at: null,
last_replied_at: null,
last_contacted_at: null,
last_email_opened_at: null,
last_email_clicked_at: null,
language_override: null,
browser: null,
browser_version: null,
browser_language: null,
os: null,
location: {
type: 'location',
country: null,
region: null,
city: null,
country_code: null,
continent_code: null,
},
android_app_name: null,
android_app_version: null,
android_device: null,
android_os_version: null,
android_sdk_version: null,
android_last_seen_at: null,
ios_app_name: null,
ios_app_version: null,
ios_device: null,
ios_os_version: null,
ios_sdk_version: null,
ios_last_seen_at: null,
custom_attributes: {},
tags: {
type: 'list',
data: [],
url: '/contacts/67a9b9dfcc14109e073fbe19/tags',
total_count: 0,
has_more: false,
},
notes: {
type: 'list',
data: [],
url: '/contacts/67a9b9dfcc14109e073fbe19/notes',
total_count: 0,
has_more: false,
},
companies: {
type: 'list',
data: [],
url: '/contacts/67a9b9dfcc14109e073fbe19/companies',
total_count: 0,
has_more: false,
},
opted_out_subscription_types: {
type: 'list',
data: [],
url: '/contacts/67a9b9dfcc14109e073fbe19/subscriptions',
total_count: 0,
has_more: false,
},
opted_in_subscription_types: {
type: 'list',
data: [],
url: '/contacts/67a9b9dfcc14109e073fbe19/subscriptions',
total_count: 0,
has_more: false,
},
utm_campaign: null,
utm_content: null,
utm_medium: null,
utm_source: null,
utm_term: null,
referrer: null,
sms_consent: false,
unsubscribed_from_sms: false,
enabled_push_messaging: null,
},
});

View File

@@ -0,0 +1,64 @@
import { createTrigger, TriggerStrategy, Property } from '@activepieces/pieces-framework';
import { stripHtml } from 'string-strip-html';
import { intercomAuth } from '../..';
import { intercomClient } from '../common';
export const noteAddedToConversation = createTrigger({
// auth: check https://www.activepieces.com/docs/developers/piece-reference/authentication,
name: 'noteAddedToConversation',
displayName: 'Note added to conversation',
description: 'Triggers when a note is added to a conversation',
props: {
keyword: Property.ShortText({
displayName: 'Keyword (optional)',
required: false,
}),
},
sampleData: undefined,
auth: intercomAuth,
type: TriggerStrategy.APP_WEBHOOK,
async onEnable(context) {
const client = intercomClient(context.auth);
const response = await client.admins.identify();
if (!response.app?.id_code) {
throw new Error('Could not find admin id code');
}
context.app.createListeners({
events: ['conversation.admin.noted'],
identifierValue: response['app']['id_code'],
});
},
async onDisable(context) {
// implement webhook deletion logic
},
async run(context) {
const keyword = context.propsValue.keyword;
const payloadBody = context.payload.body as IntercomPayloadBodyType;
if (
!keyword ||
payloadBody?.data?.item?.conversation_parts.conversation_parts.some((part) =>
stripHtml(part.body)
.result.split(/\s/)
.some((word) => word === keyword),
)
) {
return [payloadBody];
}
return [];
},
});
type IntercomPayloadBodyType = {
data: {
item: {
conversation_parts: {
conversation_parts: {
body: string;
}[];
};
};
};
};

View File

@@ -0,0 +1,32 @@
import { createTrigger, TriggerStrategy } from '@activepieces/pieces-framework';
import { intercomAuth } from '../..';
import { intercomClient } from '../common';
export const replyFromAdmin = createTrigger({
// auth: check https://www.activepieces.com/docs/developers/piece-reference/authentication,
name: 'replyFromAdmin',
displayName: 'Reply from an Intercom admin',
description: 'Triggers when a reply is received from an Intercom admin (not a user or lead)',
props: {},
sampleData: undefined,
auth: intercomAuth,
type: TriggerStrategy.APP_WEBHOOK,
async onEnable(context) {
const client = intercomClient(context.auth);
const response = await client.admins.identify();
if (!response.app?.id_code) {
throw new Error('Could not find admin id code');
}
context.app.createListeners({
events: ['conversation.admin.replied'],
identifierValue: response['app']['id_code'],
});
},
async onDisable(context) {
// implement webhook deletion logic
},
async run(context) {
return [context.payload.body];
},
});

View File

@@ -0,0 +1,32 @@
import { createTrigger, TriggerStrategy } from '@activepieces/pieces-framework';
import { intercomAuth } from '../..';
import { intercomClient } from '../common';
export const replyFromUser = createTrigger({
// auth: check https://www.activepieces.com/docs/developers/piece-reference/authentication,
name: 'replyFromUser',
displayName: 'Reply from a user or lead',
description: 'Triggers when a reply is received from a user or lead (not an admin)',
props: {},
sampleData: undefined,
auth: intercomAuth,
type: TriggerStrategy.APP_WEBHOOK,
async onEnable(context) {
const client = intercomClient(context.auth);
const response = await client.admins.identify();
if (!response.app?.id_code) {
throw new Error('Could not find admin id code');
}
context.app.createListeners({
events: ['conversation.user.replied'],
identifierValue: response['app']['id_code'],
});
},
async onDisable(context) {
// implement webhook deletion logic
},
async run(context) {
return [context.payload.body];
},
});

View File

@@ -0,0 +1,233 @@
import { createTrigger, TriggerStrategy } from '@activepieces/pieces-framework';
import { intercomAuth } from '../..';
import { intercomClient } from '../common';
import { tagIdProp } from '../common/props';
export const tagAddedToLeadTrigger = createTrigger({
name: 'tag-added-to-lead',
displayName: 'Tag Added to Lead',
description: 'Triggers when a tag is added to a lead.',
props: {
tagId: tagIdProp('Tag', false),
},
auth: intercomAuth,
type: TriggerStrategy.APP_WEBHOOK,
async onEnable(context) {
const client = intercomClient(context.auth);
const response = await client.admins.identify();
if (!response.app?.id_code) {
throw new Error('Could not find admin id code');
}
context.app.createListeners({
events: ['contact.lead.tag.created'],
identifierValue: response['app']['id_code'],
});
},
async onDisable(context) {
// implement webhook deletion logic
},
async test(context) {
const client = intercomClient(context.auth);
if (context.propsValue.tagId) {
const response = await client.contacts.search({
query: {
operator: 'AND',
value: [
{
field: 'tag_id',
operator: '=',
value: context.propsValue.tagId,
},
{
field: 'role',
operator: '=',
value: 'lead',
},
],
},
pagination: { per_page: 5 },
});
const tag = await client.tags.find({ tag_id: context.propsValue.tagId });
return response.data.map((item) => {
return {
type: 'contact_tag',
tag: {
type: tag.type,
id: tag.id,
name: tag.name,
},
contact: item,
};
});
}
const response = await client.contacts.search({
query: {
operator: 'AND',
value: [
{
field: 'tag_id',
operator: '!=',
value: '',
},
{
field: 'role',
operator: '=',
value: 'lead',
},
],
},
pagination: { per_page: 100 },
});
let count = 0;
const items = [];
for await (const lead of response) {
if (lead.tags && lead.tags.data.length > 0) {
const tag = await client.tags.find({ tag_id: lead.tags.data[0].id });
items.push({
type: 'contact_tag',
tag: {
type: tag.type,
id: tag.id,
name: tag.name,
},
contact: lead,
});
count++;
}
if (count >= 5) break;
}
return items;
},
async run(context) {
const tag = context.propsValue.tagId;
const payloadBody = context.payload.body as IntercomPayloadBodyType;
if (!tag || payloadBody?.data?.item?.tag.id === tag) {
return [payloadBody.data.item];
}
return [];
},
sampleData: {
type: 'contact_tag',
tag: {
type: 'tag',
id: '34',
name: 'Manual tag',
},
contact: {
type: 'contact',
id: '67a9b9dfcc14109e073fbe19',
workspace_id: 'nzekhfwb',
external_id: '5b803f65-bcec-4198-b4f4-a0588454b537',
role: 'lead',
email: 'john.doe@example.com',
phone: null,
name: 'John Doe',
avatar: null,
owner_id: null,
social_profiles: {
type: 'list',
data: [],
},
has_hard_bounced: false,
marked_email_as_spam: false,
unsubscribed_from_emails: false,
created_at: '2025-02-10T08:33:35.910+00:00',
updated_at: '2025-02-10T08:33:35.907+00:00',
signed_up_at: null,
last_seen_at: null,
last_replied_at: null,
last_contacted_at: null,
last_email_opened_at: null,
last_email_clicked_at: null,
language_override: null,
browser: null,
browser_version: null,
browser_language: null,
os: null,
location: {
type: 'location',
country: null,
region: null,
city: null,
country_code: null,
continent_code: null,
},
android_app_name: null,
android_app_version: null,
android_device: null,
android_os_version: null,
android_sdk_version: null,
android_last_seen_at: null,
ios_app_name: null,
ios_app_version: null,
ios_device: null,
ios_os_version: null,
ios_sdk_version: null,
ios_last_seen_at: null,
custom_attributes: {},
tags: {
type: 'list',
data: [],
url: '/contacts/67a9b9dfcc14109e073fbe19/tags',
total_count: 0,
has_more: false,
},
notes: {
type: 'list',
data: [],
url: '/contacts/67a9b9dfcc14109e073fbe19/notes',
total_count: 0,
has_more: false,
},
companies: {
type: 'list',
data: [],
url: '/contacts/67a9b9dfcc14109e073fbe19/companies',
total_count: 0,
has_more: false,
},
opted_out_subscription_types: {
type: 'list',
data: [],
url: '/contacts/67a9b9dfcc14109e073fbe19/subscriptions',
total_count: 0,
has_more: false,
},
opted_in_subscription_types: {
type: 'list',
data: [],
url: '/contacts/67a9b9dfcc14109e073fbe19/subscriptions',
total_count: 0,
has_more: false,
},
utm_campaign: null,
utm_content: null,
utm_medium: null,
utm_source: null,
utm_term: null,
referrer: null,
sms_consent: false,
unsubscribed_from_sms: false,
enabled_push_messaging: null,
},
},
});
type IntercomPayloadBodyType = {
data: {
item: {
tag: {
id: string;
};
};
};
};

View File

@@ -0,0 +1,233 @@
import { createTrigger, TriggerStrategy } from '@activepieces/pieces-framework';
import { intercomAuth } from '../..';
import { intercomClient } from '../common';
import { tagIdProp } from '../common/props';
export const tagAddedToUserTrigger = createTrigger({
name: 'tag-added-to-user',
displayName: 'Tag Added to User',
description: 'Triggers when a tag is added to a user.',
props: {
tagId: tagIdProp('Tag', false),
},
auth: intercomAuth,
type: TriggerStrategy.APP_WEBHOOK,
async onEnable(context) {
const client = intercomClient(context.auth);
const response = await client.admins.identify();
if (!response.app?.id_code) {
throw new Error('Could not find admin id code');
}
context.app.createListeners({
events: ['contact.user.tag.created'],
identifierValue: response['app']['id_code'],
});
},
async onDisable(context) {
// implement webhook deletion logic
},
async test(context) {
const client = intercomClient(context.auth);
if (context.propsValue.tagId) {
const response = await client.contacts.search({
query: {
operator: 'AND',
value: [
{
field: 'tag_id',
operator: '=',
value: context.propsValue.tagId,
},
{
field: 'role',
operator: '=',
value: 'user',
},
],
},
pagination: { per_page: 5 },
});
const tag = await client.tags.find({ tag_id: context.propsValue.tagId });
return response.data.map((item) => {
return {
type: 'contact_tag',
tag: {
type: tag.type,
id: tag.id,
name: tag.name,
},
contact: item,
};
});
}
const response = await client.contacts.search({
query: {
operator: 'AND',
value: [
{
field: 'tag_id',
operator: '!=',
value: '',
},
{
field: 'role',
operator: '=',
value: 'user',
},
],
},
pagination: { per_page: 100 },
});
let count = 0;
const items = [];
for await (const user of response) {
if (user.tags && user.tags.data.length > 0) {
const tag = await client.tags.find({ tag_id: user.tags.data[0].id });
items.push({
type: 'contact_tag',
tag: {
type: tag.type,
id: tag.id,
name: tag.name,
},
contact: user,
});
count++;
}
if (count >= 5) break;
}
return items;
},
async run(context) {
const tag = context.propsValue.tagId;
const payloadBody = context.payload.body as IntercomPayloadBodyType;
if (!tag || payloadBody?.data?.item?.tag.id === tag) {
return [payloadBody.data.item];
}
return [];
},
sampleData: {
type: 'contact_tag',
tag: {
type: 'tag',
id: '34',
name: 'Manual tag',
},
contact: {
type: 'contact',
id: '67a9b9dfcc14109e073fbe19',
workspace_id: 'nzekhfwb',
external_id: '5b803f65-bcec-4198-b4f4-a0588454b537',
role: 'user',
email: 'john.doe@example.com',
phone: null,
name: 'John Doe',
avatar: null,
owner_id: null,
social_profiles: {
type: 'list',
data: [],
},
has_hard_bounced: false,
marked_email_as_spam: false,
unsubscribed_from_emails: false,
created_at: '2025-02-10T08:33:35.910+00:00',
updated_at: '2025-02-10T08:33:35.907+00:00',
signed_up_at: null,
last_seen_at: null,
last_replied_at: null,
last_contacted_at: null,
last_email_opened_at: null,
last_email_clicked_at: null,
language_override: null,
browser: null,
browser_version: null,
browser_language: null,
os: null,
location: {
type: 'location',
country: null,
region: null,
city: null,
country_code: null,
continent_code: null,
},
android_app_name: null,
android_app_version: null,
android_device: null,
android_os_version: null,
android_sdk_version: null,
android_last_seen_at: null,
ios_app_name: null,
ios_app_version: null,
ios_device: null,
ios_os_version: null,
ios_sdk_version: null,
ios_last_seen_at: null,
custom_attributes: {},
tags: {
type: 'list',
data: [],
url: '/contacts/67a9b9dfcc14109e073fbe19/tags',
total_count: 0,
has_more: false,
},
notes: {
type: 'list',
data: [],
url: '/contacts/67a9b9dfcc14109e073fbe19/notes',
total_count: 0,
has_more: false,
},
companies: {
type: 'list',
data: [],
url: '/contacts/67a9b9dfcc14109e073fbe19/companies',
total_count: 0,
has_more: false,
},
opted_out_subscription_types: {
type: 'list',
data: [],
url: '/contacts/67a9b9dfcc14109e073fbe19/subscriptions',
total_count: 0,
has_more: false,
},
opted_in_subscription_types: {
type: 'list',
data: [],
url: '/contacts/67a9b9dfcc14109e073fbe19/subscriptions',
total_count: 0,
has_more: false,
},
utm_campaign: null,
utm_content: null,
utm_medium: null,
utm_source: null,
utm_term: null,
referrer: null,
sms_consent: false,
unsubscribed_from_sms: false,
enabled_push_messaging: null,
},
},
});
type IntercomPayloadBodyType = {
data: {
item: {
tag: {
id: string;
};
};
};
};