Skip to content

Commit 0916b19

Browse files
authored
improvement(instantly): validate integration against live API, add lead/campaign lifecycle tools (#5448)
* improvement(instantly): validate integration against live API, add lead/campaign lifecycle tools - Verify all existing Instantly tools against the live API v2 spec - Add instantly_patch_lead, instantly_pause_campaign, instantly_delete_campaign - Fix activate_campaign response mapping to surface the full campaign object - Restore status/ai_sales_agent_id list_campaigns filters * fix(instantly): guard against empty patch_lead request body Follows the same pattern used in tools/langsmith/update_run.ts.
1 parent 0363451 commit 0916b19

10 files changed

Lines changed: 350 additions & 20 deletions

File tree

apps/sim/blocks/blocks/instantly.ts

Lines changed: 44 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,23 @@ import type { InstantlyResponse } from '@/tools/instantly/types'
66
import { getTrigger } from '@/triggers'
77

88
const LEAD_LIST_OPERATIONS = ['list_leads'] as const
9-
const LEAD_ID_OPERATIONS = ['get_lead'] as const
9+
const LEAD_ID_OPERATIONS = ['get_lead', 'patch_lead'] as const
1010
const LEAD_CREATE_OPERATIONS = ['create_lead'] as const
11+
const LEAD_PATCH_OPERATIONS = ['patch_lead'] as const
12+
const LEAD_MUTATION_FIELD_OPERATIONS = [
13+
...LEAD_CREATE_OPERATIONS,
14+
...LEAD_PATCH_OPERATIONS,
15+
] as const
1116
const LEAD_DELETE_OPERATIONS = ['delete_leads'] as const
1217
const LEAD_INTEREST_OPERATIONS = ['update_lead_interest_status'] as const
1318
const CAMPAIGN_LIST_OPERATIONS = ['list_campaigns'] as const
1419
const CAMPAIGN_MUTATION_OPERATIONS = ['create_campaign', 'patch_campaign'] as const
15-
const CAMPAIGN_ID_OPERATIONS = ['patch_campaign', 'activate_campaign'] as const
20+
const CAMPAIGN_ID_OPERATIONS = [
21+
'patch_campaign',
22+
'activate_campaign',
23+
'pause_campaign',
24+
'delete_campaign',
25+
] as const
1626
const EMAIL_LIST_OPERATIONS = ['list_emails'] as const
1727
const EMAIL_REPLY_OPERATIONS = ['reply_to_email'] as const
1828
const LEAD_LIST_LIST_OPERATIONS = ['list_lead_lists'] as const
@@ -51,7 +61,7 @@ export const InstantlyBlock: BlockConfig<InstantlyResponse> = {
5161
name: 'Instantly',
5262
description: 'Manage Instantly leads, campaigns, emails, and lead lists',
5363
longDescription:
54-
'Integrate Instantly API V2 into workflows. Create and list leads, manage lead interest status, delete leads in bulk, list and create campaigns, reply to emails, and manage lead lists.',
64+
'Integrate Instantly API V2 into workflows. Create, update, and list leads, manage lead interest status, delete leads in bulk, list, create, patch, activate, pause, and delete campaigns, reply to emails, and manage lead lists.',
5565
docsLink: 'https://docs.sim.ai/integrations/instantly',
5666
category: 'tools',
5767
integrationType: IntegrationType.Email,
@@ -67,12 +77,15 @@ export const InstantlyBlock: BlockConfig<InstantlyResponse> = {
6777
{ label: 'List Leads', id: 'list_leads' },
6878
{ label: 'Get Lead', id: 'get_lead' },
6979
{ label: 'Create Lead', id: 'create_lead' },
80+
{ label: 'Patch Lead', id: 'patch_lead' },
7081
{ label: 'Delete Leads', id: 'delete_leads' },
7182
{ label: 'Update Lead Interest Status', id: 'update_lead_interest_status' },
7283
{ label: 'List Campaigns', id: 'list_campaigns' },
7384
{ label: 'Create Campaign', id: 'create_campaign' },
7485
{ label: 'Patch Campaign', id: 'patch_campaign' },
7586
{ label: 'Activate Campaign', id: 'activate_campaign' },
87+
{ label: 'Pause Campaign', id: 'pause_campaign' },
88+
{ label: 'Delete Campaign', id: 'delete_campaign' },
7689
{ label: 'List Emails', id: 'list_emails' },
7790
{ label: 'Reply To Email', id: 'reply_to_email' },
7891
{ label: 'List Lead Lists', id: 'list_lead_lists' },
@@ -134,60 +147,60 @@ export const InstantlyBlock: BlockConfig<InstantlyResponse> = {
134147
title: 'First Name',
135148
type: 'short-input',
136149
placeholder: 'Jane',
137-
condition: { field: 'operation', value: [...LEAD_CREATE_OPERATIONS] },
150+
condition: { field: 'operation', value: [...LEAD_MUTATION_FIELD_OPERATIONS] },
138151
},
139152
{
140153
id: 'lastName',
141154
title: 'Last Name',
142155
type: 'short-input',
143156
placeholder: 'Doe',
144-
condition: { field: 'operation', value: [...LEAD_CREATE_OPERATIONS] },
157+
condition: { field: 'operation', value: [...LEAD_MUTATION_FIELD_OPERATIONS] },
145158
},
146159
{
147160
id: 'companyName',
148161
title: 'Company Name',
149162
type: 'short-input',
150163
placeholder: 'Acme Inc.',
151-
condition: { field: 'operation', value: [...LEAD_CREATE_OPERATIONS] },
164+
condition: { field: 'operation', value: [...LEAD_MUTATION_FIELD_OPERATIONS] },
152165
},
153166
{
154167
id: 'jobTitle',
155168
title: 'Job Title',
156169
type: 'short-input',
157170
placeholder: 'Head of Growth',
158-
condition: { field: 'operation', value: [...LEAD_CREATE_OPERATIONS] },
171+
condition: { field: 'operation', value: [...LEAD_MUTATION_FIELD_OPERATIONS] },
159172
mode: 'advanced',
160173
},
161174
{
162175
id: 'phone',
163176
title: 'Phone',
164177
type: 'short-input',
165178
placeholder: '+1234567890',
166-
condition: { field: 'operation', value: [...LEAD_CREATE_OPERATIONS] },
179+
condition: { field: 'operation', value: [...LEAD_MUTATION_FIELD_OPERATIONS] },
167180
mode: 'advanced',
168181
},
169182
{
170183
id: 'website',
171184
title: 'Website',
172185
type: 'short-input',
173186
placeholder: 'https://example.com',
174-
condition: { field: 'operation', value: [...LEAD_CREATE_OPERATIONS] },
187+
condition: { field: 'operation', value: [...LEAD_MUTATION_FIELD_OPERATIONS] },
175188
mode: 'advanced',
176189
},
177190
{
178191
id: 'personalization',
179192
title: 'Personalization',
180193
type: 'long-input',
181194
placeholder: 'Personalized opening line',
182-
condition: { field: 'operation', value: [...LEAD_CREATE_OPERATIONS] },
195+
condition: { field: 'operation', value: [...LEAD_MUTATION_FIELD_OPERATIONS] },
183196
mode: 'advanced',
184197
},
185198
{
186199
id: 'customVariables',
187200
title: 'Custom Variables',
188201
type: 'long-input',
189202
placeholder: '{"past_customer": true, "industry": "SaaS"}',
190-
condition: { field: 'operation', value: [...LEAD_CREATE_OPERATIONS] },
203+
condition: { field: 'operation', value: [...LEAD_MUTATION_FIELD_OPERATIONS] },
191204
wandConfig: {
192205
enabled: true,
193206
prompt:
@@ -266,23 +279,23 @@ export const InstantlyBlock: BlockConfig<InstantlyResponse> = {
266279
title: 'Lead Interest Status',
267280
type: 'short-input',
268281
placeholder: '1',
269-
condition: { field: 'operation', value: [...LEAD_CREATE_OPERATIONS] },
282+
condition: { field: 'operation', value: [...LEAD_MUTATION_FIELD_OPERATIONS] },
270283
mode: 'advanced',
271284
},
272285
{
273286
id: 'potentialLeadValue',
274287
title: 'Potential Lead Value',
275288
type: 'short-input',
276289
placeholder: 'High',
277-
condition: { field: 'operation', value: [...LEAD_CREATE_OPERATIONS] },
290+
condition: { field: 'operation', value: [...LEAD_MUTATION_FIELD_OPERATIONS] },
278291
mode: 'advanced',
279292
},
280293
{
281294
id: 'assignedTo',
282295
title: 'Assigned To',
283296
type: 'short-input',
284297
placeholder: 'Organization user UUID',
285-
condition: { field: 'operation', value: [...LEAD_CREATE_OPERATIONS] },
298+
condition: { field: 'operation', value: [...LEAD_MUTATION_FIELD_OPERATIONS] },
286299
mode: 'advanced',
287300
},
288301
{
@@ -842,12 +855,15 @@ export const InstantlyBlock: BlockConfig<InstantlyResponse> = {
842855
'instantly_list_leads',
843856
'instantly_get_lead',
844857
'instantly_create_lead',
858+
'instantly_patch_lead',
845859
'instantly_delete_leads',
846860
'instantly_update_lead_interest_status',
847861
'instantly_list_campaigns',
848862
'instantly_create_campaign',
849863
'instantly_patch_campaign',
850864
'instantly_activate_campaign',
865+
'instantly_pause_campaign',
866+
'instantly_delete_campaign',
851867
'instantly_list_emails',
852868
'instantly_reply_to_email',
853869
'instantly_list_lead_lists',
@@ -1350,5 +1366,19 @@ export const InstantlyBlockMeta = {
13501366
content:
13511367
'# Campaign Performance Snapshot\n\nGive a quick read on how outreach is going across campaigns.\n\n## Steps\n1. List campaigns and note which are active.\n2. For each active campaign, list leads and tally counts by interest status.\n3. Pull recent emails to gauge reply volume.\n\n## Output\nReturn a per-campaign snapshot: total leads, breakdown by interest status, and reply activity, highlighting the top-performing campaign.',
13521368
},
1369+
{
1370+
name: 'clean-up-lead-data',
1371+
description:
1372+
'Correct or enrich existing lead records so personalization and CRM sync stay accurate.',
1373+
content:
1374+
'# Clean Up Lead Data\n\nKeep lead records accurate after enrichment, verification, or manual review.\n\n## Steps\n1. Look up the lead by ID or email.\n2. Compare the current fields against the corrected or enriched data.\n3. Patch the lead with the updated first name, last name, company, job title, phone, website, or custom variables.\n\n## Output\nReturn the updated lead record and a summary of which fields changed.',
1375+
},
1376+
{
1377+
name: 'pause-underperforming-campaigns',
1378+
description:
1379+
'Detect campaigns with poor reply or interest rates and pause them to protect sender reputation.',
1380+
content:
1381+
'# Pause Underperforming Campaigns\n\nProtect domain and inbox reputation by pausing cold-email campaigns that are not converting.\n\n## Steps\n1. List active campaigns.\n2. For each campaign, list its leads and tally reply and interest counts.\n3. Flag campaigns below a reply-rate threshold.\n4. Pause each flagged campaign so no further emails are sent.\n\n## Output\nReturn which campaigns were paused, their reply rates, and the campaigns left active for comparison.',
1382+
},
13531383
],
13541384
} as const satisfies BlockMeta

apps/sim/tools/instantly/activate_campaign.ts

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
import type {
22
InstantlyActivateCampaignParams,
3-
InstantlyCampaignResponse,
3+
InstantlyCampaignActionResponse,
44
} from '@/tools/instantly/types'
55
import {
6-
campaignOutputs,
6+
campaignActionOutputs,
7+
getMessage,
78
instantlyBaseParamFields,
89
instantlyHeaders,
910
instantlyUrl,
@@ -14,7 +15,7 @@ import type { ToolConfig } from '@/tools/types'
1415

1516
export const activateCampaignTool: ToolConfig<
1617
InstantlyActivateCampaignParams,
17-
InstantlyCampaignResponse
18+
InstantlyCampaignActionResponse
1819
> = {
1920
id: 'instantly_activate_campaign',
2021
name: 'Instantly Activate Campaign',
@@ -45,8 +46,9 @@ export const activateCampaignTool: ToolConfig<
4546
id: campaign.id,
4647
name: campaign.name,
4748
status: campaign.status,
49+
message: getMessage(data),
4850
},
4951
}
5052
},
51-
outputs: campaignOutputs,
53+
outputs: campaignActionOutputs,
5254
}
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
import type {
2+
InstantlyCampaignActionResponse,
3+
InstantlyDeleteCampaignParams,
4+
} from '@/tools/instantly/types'
5+
import {
6+
campaignActionOutputs,
7+
getMessage,
8+
instantlyBaseParamFields,
9+
instantlyHeaders,
10+
instantlyUrl,
11+
mapCampaign,
12+
parseInstantlyResponse,
13+
} from '@/tools/instantly/utils'
14+
import type { ToolConfig } from '@/tools/types'
15+
16+
export const deleteCampaignTool: ToolConfig<
17+
InstantlyDeleteCampaignParams,
18+
InstantlyCampaignActionResponse
19+
> = {
20+
id: 'instantly_delete_campaign',
21+
name: 'Instantly Delete Campaign',
22+
description: 'Permanently deletes an Instantly V2 campaign.',
23+
version: '1.0.0',
24+
params: {
25+
...instantlyBaseParamFields,
26+
campaignId: {
27+
type: 'string',
28+
required: true,
29+
visibility: 'user-or-llm',
30+
description: 'Campaign ID',
31+
},
32+
},
33+
request: {
34+
url: (params) => instantlyUrl(`/api/v2/campaigns/${params.campaignId.trim()}`),
35+
method: 'DELETE',
36+
headers: instantlyHeaders,
37+
},
38+
transformResponse: async (response) => {
39+
const data = await parseInstantlyResponse(response)
40+
const campaign = mapCampaign(data)
41+
42+
return {
43+
success: true,
44+
output: {
45+
campaign,
46+
id: campaign.id,
47+
name: campaign.name,
48+
status: campaign.status,
49+
message: getMessage(data),
50+
},
51+
}
52+
},
53+
outputs: campaignActionOutputs,
54+
}

apps/sim/tools/instantly/index.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,16 @@ export { activateCampaignTool as instantlyActivateCampaignTool } from '@/tools/i
22
export { createCampaignTool as instantlyCreateCampaignTool } from '@/tools/instantly/create_campaign'
33
export { createLeadTool as instantlyCreateLeadTool } from '@/tools/instantly/create_lead'
44
export { createLeadListTool as instantlyCreateLeadListTool } from '@/tools/instantly/create_lead_list'
5+
export { deleteCampaignTool as instantlyDeleteCampaignTool } from '@/tools/instantly/delete_campaign'
56
export { deleteLeadsTool as instantlyDeleteLeadsTool } from '@/tools/instantly/delete_leads'
67
export { getLeadTool as instantlyGetLeadTool } from '@/tools/instantly/get_lead'
78
export { listCampaignsTool as instantlyListCampaignsTool } from '@/tools/instantly/list_campaigns'
89
export { listEmailsTool as instantlyListEmailsTool } from '@/tools/instantly/list_emails'
910
export { listLeadListsTool as instantlyListLeadListsTool } from '@/tools/instantly/list_lead_lists'
1011
export { listLeadsTool as instantlyListLeadsTool } from '@/tools/instantly/list_leads'
1112
export { patchCampaignTool as instantlyPatchCampaignTool } from '@/tools/instantly/patch_campaign'
13+
export { patchLeadTool as instantlyPatchLeadTool } from '@/tools/instantly/patch_lead'
14+
export { pauseCampaignTool as instantlyPauseCampaignTool } from '@/tools/instantly/pause_campaign'
1215
export { replyToEmailTool as instantlyReplyToEmailTool } from '@/tools/instantly/reply_to_email'
1316
export * from '@/tools/instantly/types'
1417
export { updateLeadInterestStatusTool as instantlyUpdateLeadInterestStatusTool } from '@/tools/instantly/update_lead_interest_status'

apps/sim/tools/instantly/list_campaigns.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ export const listCampaignsTool: ToolConfig<
5252
type: 'string',
5353
required: false,
5454
visibility: 'user-or-llm',
55-
description: 'AI Sales Agent ID filter',
55+
description: 'Filter campaigns by AI Sales Agent ID',
5656
},
5757
status: {
5858
type: 'number',

0 commit comments

Comments
 (0)