@workbuddy/piece-workbuddy-vnext 1.0.4 → 1.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (208) hide show
  1. package/package.json +1 -1
  2. package/src/index.d.ts.map +1 -1
  3. package/src/index.js +89 -83
  4. package/src/index.js.map +1 -1
  5. package/src/index.ts +29 -17
  6. package/src/lib/actions/agents.d.ts.map +1 -1
  7. package/src/lib/actions/agents.js +6 -4
  8. package/src/lib/actions/agents.js.map +1 -1
  9. package/src/lib/actions/agents.ts +8 -4
  10. package/src/lib/actions/attachments.d.ts.map +1 -1
  11. package/src/lib/actions/attachments.js +2 -1
  12. package/src/lib/actions/attachments.js.map +1 -1
  13. package/src/lib/actions/attachments.ts +3 -1
  14. package/src/lib/actions/{crm->-companies.d.ts → crm-companies.d.ts} +1 -1
  15. package/src/lib/actions/crm-companies.d.ts.map +1 -0
  16. package/src/lib/actions/{crm->-companies.js → crm-companies.js} +1 -1
  17. package/src/lib/actions/{crm->-invites.js.map → crm-companies.js.map} +1 -1
  18. package/src/lib/actions/{crm->-contacts.d.ts → crm-contacts.d.ts} +1 -1
  19. package/src/lib/actions/crm-contacts.d.ts.map +1 -0
  20. package/src/lib/actions/{crm->-contacts.js → crm-contacts.js} +1 -1
  21. package/src/lib/actions/crm-contacts.js.map +1 -0
  22. package/src/lib/actions/{crm->-contractors.d.ts → crm-contractors.d.ts} +1 -1
  23. package/src/lib/actions/crm-contractors.d.ts.map +1 -0
  24. package/src/lib/actions/{crm->-contractors.js → crm-contractors.js} +1 -1
  25. package/src/lib/actions/{crm->-employees.js.map → crm-contractors.js.map} +1 -1
  26. package/src/lib/actions/{crm->-customers.d.ts → crm-customers.d.ts} +1 -1
  27. package/src/lib/actions/crm-customers.d.ts.map +1 -0
  28. package/src/lib/actions/{crm->-customers.js → crm-customers.js} +1 -1
  29. package/src/lib/actions/crm-customers.js.map +1 -0
  30. package/src/lib/actions/{crm->-employees.d.ts → crm-employees.d.ts} +1 -1
  31. package/src/lib/actions/crm-employees.d.ts.map +1 -0
  32. package/src/lib/actions/{crm->-employees.js → crm-employees.js} +1 -1
  33. package/src/lib/actions/crm-employees.js.map +1 -0
  34. package/src/lib/actions/{crm->-external-users.d.ts → crm-external-users.d.ts} +1 -1
  35. package/src/lib/actions/crm-external-users.d.ts.map +1 -0
  36. package/src/lib/actions/{crm->-external-users.js → crm-external-users.js} +1 -1
  37. package/src/lib/actions/crm-external-users.js.map +1 -0
  38. package/src/lib/actions/{crm->-invites.d.ts → crm-invites.d.ts} +1 -1
  39. package/src/lib/actions/crm-invites.d.ts.map +1 -0
  40. package/src/lib/actions/{crm->-invites.js → crm-invites.js} +1 -1
  41. package/src/lib/actions/crm-invites.js.map +1 -0
  42. package/src/lib/actions/{crm->-sites.d.ts → crm-sites.d.ts} +1 -1
  43. package/src/lib/actions/crm-sites.d.ts.map +1 -0
  44. package/src/lib/actions/{crm->-sites.js → crm-sites.js} +1 -1
  45. package/src/lib/actions/crm-sites.js.map +1 -0
  46. package/src/lib/actions/{crm->-suppliers.d.ts → crm-suppliers.d.ts} +1 -1
  47. package/src/lib/actions/crm-suppliers.d.ts.map +1 -0
  48. package/src/lib/actions/{crm->-suppliers.js → crm-suppliers.js} +1 -1
  49. package/src/lib/actions/crm-suppliers.js.map +1 -0
  50. package/src/lib/actions/flags.d.ts +34 -0
  51. package/src/lib/actions/flags.d.ts.map +1 -0
  52. package/src/lib/actions/flags.js +185 -0
  53. package/src/lib/actions/flags.js.map +1 -0
  54. package/src/lib/actions/flags.ts +201 -0
  55. package/src/lib/actions/index.d.ts +18 -17
  56. package/src/lib/actions/index.d.ts.map +1 -1
  57. package/src/lib/actions/index.js +18 -17
  58. package/src/lib/actions/index.js.map +1 -1
  59. package/src/lib/actions/index.ts +18 -17
  60. package/src/lib/actions/{jobs->-activities.d.ts → jobs-activities.d.ts} +15 -5
  61. package/src/lib/actions/jobs-activities.d.ts.map +1 -0
  62. package/src/lib/actions/{jobs->-activities.js → jobs-activities.js} +110 -59
  63. package/src/lib/actions/jobs-activities.js.map +1 -0
  64. package/src/lib/actions/{jobs->-activities.ts → jobs-activities.ts} +118 -57
  65. package/src/lib/actions/{jobs->-contacts.d.ts → jobs-contacts.d.ts} +1 -1
  66. package/src/lib/actions/jobs-contacts.d.ts.map +1 -0
  67. package/src/lib/actions/{jobs->-contacts.js → jobs-contacts.js} +5 -5
  68. package/src/lib/actions/jobs-contacts.js.map +1 -0
  69. package/src/lib/actions/{jobs->-contacts.ts → jobs-contacts.ts} +4 -4
  70. package/src/lib/actions/{jobs->-files.d.ts → jobs-files.d.ts} +1 -1
  71. package/src/lib/actions/jobs-files.d.ts.map +1 -0
  72. package/src/lib/actions/{jobs->-files.js → jobs-files.js} +9 -9
  73. package/src/lib/actions/jobs-files.js.map +1 -0
  74. package/src/lib/actions/{jobs->-files.ts → jobs-files.ts} +8 -8
  75. package/src/lib/actions/{jobs->-tasks.d.ts → jobs-tasks.d.ts} +4 -2
  76. package/src/lib/actions/jobs-tasks.d.ts.map +1 -0
  77. package/src/lib/actions/{jobs->-tasks.js → jobs-tasks.js} +61 -37
  78. package/src/lib/actions/jobs-tasks.js.map +1 -0
  79. package/src/lib/actions/{jobs->-tasks.ts → jobs-tasks.ts} +64 -36
  80. package/src/lib/actions/jobs.d.ts +4 -3
  81. package/src/lib/actions/jobs.d.ts.map +1 -1
  82. package/src/lib/actions/jobs.js +90 -72
  83. package/src/lib/actions/jobs.js.map +1 -1
  84. package/src/lib/actions/jobs.ts +94 -72
  85. package/src/lib/actions/mcp.d.ts +1 -1
  86. package/src/lib/actions/mcp.d.ts.map +1 -1
  87. package/src/lib/actions/mcp.js +7 -6
  88. package/src/lib/actions/mcp.js.map +1 -1
  89. package/src/lib/actions/mcp.ts +8 -6
  90. package/src/lib/actions/settings.js +1 -1
  91. package/src/lib/actions/settings.js.map +1 -1
  92. package/src/lib/actions/settings.ts +1 -1
  93. package/src/lib/actions/{stages->-activities.d.ts → stages-activities.d.ts} +24 -5
  94. package/src/lib/actions/stages-activities.d.ts.map +1 -0
  95. package/src/lib/actions/{stages->-activities.js → stages-activities.js} +164 -68
  96. package/src/lib/actions/stages-activities.js.map +1 -0
  97. package/src/lib/actions/{stages->-activities.ts → stages-activities.ts} +172 -66
  98. package/src/lib/actions/{stages->-files.d.ts → stages-files.d.ts} +5 -1
  99. package/src/lib/actions/stages-files.d.ts.map +1 -0
  100. package/src/lib/actions/{stages->-files.js → stages-files.js} +35 -15
  101. package/src/lib/actions/stages-files.js.map +1 -0
  102. package/src/lib/actions/{stages->-files.ts → stages-files.ts} +34 -14
  103. package/src/lib/actions/{stages->-resources.d.ts → stages-resources.d.ts} +1 -1
  104. package/src/lib/actions/stages-resources.d.ts.map +1 -0
  105. package/src/lib/actions/{stages->-resources.js → stages-resources.js} +7 -5
  106. package/src/lib/actions/stages-resources.js.map +1 -0
  107. package/src/lib/actions/{stages->-resources.ts → stages-resources.ts} +8 -4
  108. package/src/lib/actions/{stages->-tasks.d.ts → stages-tasks.d.ts} +8 -2
  109. package/src/lib/actions/stages-tasks.d.ts.map +1 -0
  110. package/src/lib/actions/{stages->-tasks.js → stages-tasks.js} +91 -47
  111. package/src/lib/actions/stages-tasks.js.map +1 -0
  112. package/src/lib/actions/{stages->-tasks.ts → stages-tasks.ts} +94 -46
  113. package/src/lib/actions/stages.d.ts +6 -2
  114. package/src/lib/actions/stages.d.ts.map +1 -1
  115. package/src/lib/actions/stages.js +77 -27
  116. package/src/lib/actions/stages.js.map +1 -1
  117. package/src/lib/actions/stages.ts +88 -27
  118. package/src/lib/actions/webhooks-v2.js +15 -15
  119. package/src/lib/actions/webhooks-v2.js.map +1 -1
  120. package/src/lib/actions/webhooks-v2.ts +15 -15
  121. package/src/lib/auth.js +2 -2
  122. package/src/lib/auth.js.map +1 -1
  123. package/src/lib/auth.ts +2 -2
  124. package/src/lib/triggers/activity.d.ts.map +1 -1
  125. package/src/lib/triggers/activity.js +54 -42
  126. package/src/lib/triggers/activity.js.map +1 -1
  127. package/src/lib/triggers/activity.ts +54 -42
  128. package/src/lib/triggers/bill.d.ts +240 -48
  129. package/src/lib/triggers/bill.d.ts.map +1 -1
  130. package/src/lib/triggers/bill.js +368 -88
  131. package/src/lib/triggers/bill.js.map +1 -1
  132. package/src/lib/triggers/bill.ts +368 -88
  133. package/src/lib/triggers/invoice.d.ts +240 -48
  134. package/src/lib/triggers/invoice.d.ts.map +1 -1
  135. package/src/lib/triggers/invoice.js +368 -88
  136. package/src/lib/triggers/invoice.js.map +1 -1
  137. package/src/lib/triggers/invoice.ts +368 -88
  138. package/src/lib/triggers/job.d.ts +640 -128
  139. package/src/lib/triggers/job.d.ts.map +1 -1
  140. package/src/lib/triggers/job.js +928 -208
  141. package/src/lib/triggers/job.js.map +1 -1
  142. package/src/lib/triggers/job.ts +928 -208
  143. package/src/lib/triggers/lead.d.ts +400 -80
  144. package/src/lib/triggers/lead.d.ts.map +1 -1
  145. package/src/lib/triggers/lead.js +552 -96
  146. package/src/lib/triggers/lead.js.map +1 -1
  147. package/src/lib/triggers/lead.ts +552 -96
  148. package/src/lib/triggers/opportunity.d.ts +320 -64
  149. package/src/lib/triggers/opportunity.d.ts.map +1 -1
  150. package/src/lib/triggers/opportunity.js +456 -88
  151. package/src/lib/triggers/opportunity.js.map +1 -1
  152. package/src/lib/triggers/opportunity.ts +456 -88
  153. package/src/lib/triggers/quote.d.ts +240 -48
  154. package/src/lib/triggers/quote.d.ts.map +1 -1
  155. package/src/lib/triggers/quote.js +368 -88
  156. package/src/lib/triggers/quote.js.map +1 -1
  157. package/src/lib/triggers/quote.ts +368 -88
  158. package/src/lib/triggers/stage.d.ts +480 -96
  159. package/src/lib/triggers/stage.d.ts.map +1 -1
  160. package/src/lib/triggers/stage.js +764 -220
  161. package/src/lib/triggers/stage.js.map +1 -1
  162. package/src/lib/triggers/stage.ts +764 -220
  163. package/src/lib/triggers/task.d.ts +80 -16
  164. package/src/lib/triggers/task.d.ts.map +1 -1
  165. package/src/lib/triggers/task.js +172 -68
  166. package/src/lib/triggers/task.js.map +1 -1
  167. package/src/lib/triggers/task.ts +172 -68
  168. package/src/lib/actions/crm->-companies.d.ts.map +0 -1
  169. package/src/lib/actions/crm->-companies.js.map +0 -1
  170. package/src/lib/actions/crm->-contacts.d.ts.map +0 -1
  171. package/src/lib/actions/crm->-contacts.js.map +0 -1
  172. package/src/lib/actions/crm->-contractors.d.ts.map +0 -1
  173. package/src/lib/actions/crm->-contractors.js.map +0 -1
  174. package/src/lib/actions/crm->-customers.d.ts.map +0 -1
  175. package/src/lib/actions/crm->-customers.js.map +0 -1
  176. package/src/lib/actions/crm->-employees.d.ts.map +0 -1
  177. package/src/lib/actions/crm->-external-users.d.ts.map +0 -1
  178. package/src/lib/actions/crm->-external-users.js.map +0 -1
  179. package/src/lib/actions/crm->-invites.d.ts.map +0 -1
  180. package/src/lib/actions/crm->-sites.d.ts.map +0 -1
  181. package/src/lib/actions/crm->-sites.js.map +0 -1
  182. package/src/lib/actions/crm->-suppliers.d.ts.map +0 -1
  183. package/src/lib/actions/crm->-suppliers.js.map +0 -1
  184. package/src/lib/actions/jobs->-activities.d.ts.map +0 -1
  185. package/src/lib/actions/jobs->-activities.js.map +0 -1
  186. package/src/lib/actions/jobs->-contacts.d.ts.map +0 -1
  187. package/src/lib/actions/jobs->-contacts.js.map +0 -1
  188. package/src/lib/actions/jobs->-files.d.ts.map +0 -1
  189. package/src/lib/actions/jobs->-files.js.map +0 -1
  190. package/src/lib/actions/jobs->-tasks.d.ts.map +0 -1
  191. package/src/lib/actions/jobs->-tasks.js.map +0 -1
  192. package/src/lib/actions/stages->-activities.d.ts.map +0 -1
  193. package/src/lib/actions/stages->-activities.js.map +0 -1
  194. package/src/lib/actions/stages->-files.d.ts.map +0 -1
  195. package/src/lib/actions/stages->-files.js.map +0 -1
  196. package/src/lib/actions/stages->-resources.d.ts.map +0 -1
  197. package/src/lib/actions/stages->-resources.js.map +0 -1
  198. package/src/lib/actions/stages->-tasks.d.ts.map +0 -1
  199. package/src/lib/actions/stages->-tasks.js.map +0 -1
  200. /package/src/lib/actions/{crm->-companies.ts → crm-companies.ts} +0 -0
  201. /package/src/lib/actions/{crm->-contacts.ts → crm-contacts.ts} +0 -0
  202. /package/src/lib/actions/{crm->-contractors.ts → crm-contractors.ts} +0 -0
  203. /package/src/lib/actions/{crm->-customers.ts → crm-customers.ts} +0 -0
  204. /package/src/lib/actions/{crm->-employees.ts → crm-employees.ts} +0 -0
  205. /package/src/lib/actions/{crm->-external-users.ts → crm-external-users.ts} +0 -0
  206. /package/src/lib/actions/{crm->-invites.ts → crm-invites.ts} +0 -0
  207. /package/src/lib/actions/{crm->-sites.ts → crm-sites.ts} +0 -0
  208. /package/src/lib/actions/{crm->-suppliers.ts → crm-suppliers.ts} +0 -0
@@ -8,45 +8,221 @@ export const job_created_trigger = createTrigger({
8
8
  displayName: 'Job Created',
9
9
  description: 'Triggered when a new job is created',
10
10
  props: {
11
- customer: Property.Array({
11
+ customer: Property.MultiSelectDropdown({
12
12
  displayName: 'Filter by Customer',
13
- description: 'Only trigger for specific customer IDs',
13
+ description: 'Only trigger for specific customer',
14
14
  required: false,
15
+ auth: workbuddyAuth,
16
+ refreshers: [],
17
+ options: async ({ auth }) => {
18
+ const authValue = auth as unknown as { props: { baseUrl: string; clientId: string; clientSecret: string } };
19
+ const token = await getAccessToken(authValue);
20
+ const baseUrl = authValue.props.baseUrl;
21
+ const response = await httpClient.sendRequest<{ items: Array<{ id: string; name: string }> }>({
22
+ method: HttpMethod.GET,
23
+ url: `${baseUrl}/api/v2/public/customers`,
24
+ headers: {
25
+ Authorization: `Bearer ${token}`,
26
+ 'X-WorkBuddy-Version': '2026-01',
27
+ },
28
+ });
29
+ const items = response.body?.items || [];
30
+ return {
31
+ options: items.map((item) => ({
32
+ label: item.name,
33
+ value: item.id,
34
+ })),
35
+ };
36
+ },
15
37
  }),
16
- billingCompany: Property.Array({
38
+ billingCompany: Property.MultiSelectDropdown({
17
39
  displayName: 'Filter by Billing Company',
18
- description: 'Only trigger for specific billing company IDs',
40
+ description: 'Only trigger for specific billing company',
19
41
  required: false,
42
+ auth: workbuddyAuth,
43
+ refreshers: [],
44
+ options: async ({ auth }) => {
45
+ const authValue = auth as unknown as { props: { baseUrl: string; clientId: string; clientSecret: string } };
46
+ const token = await getAccessToken(authValue);
47
+ const baseUrl = authValue.props.baseUrl;
48
+ const response = await httpClient.sendRequest<{ items: Array<{ id: string; name: string }> }>({
49
+ method: HttpMethod.GET,
50
+ url: `${baseUrl}/api/v2/public/companies`,
51
+ headers: {
52
+ Authorization: `Bearer ${token}`,
53
+ 'X-WorkBuddy-Version': '2026-01',
54
+ },
55
+ });
56
+ const items = response.body?.items || [];
57
+ return {
58
+ options: items.map((item) => ({
59
+ label: item.name,
60
+ value: item.id,
61
+ })),
62
+ };
63
+ },
20
64
  }),
21
- tag: Property.Array({
65
+ tag: Property.MultiSelectDropdown({
22
66
  displayName: 'Filter by Tags',
23
- description: 'Only trigger for specific tags IDs',
67
+ description: 'Only trigger for specific tags',
24
68
  required: false,
69
+ auth: workbuddyAuth,
70
+ refreshers: [],
71
+ options: async ({ auth }) => {
72
+ const authValue = auth as unknown as { props: { baseUrl: string; clientId: string; clientSecret: string } };
73
+ const token = await getAccessToken(authValue);
74
+ const baseUrl = authValue.props.baseUrl;
75
+ const response = await httpClient.sendRequest<{ items: Array<{ id: string; name: string }> }>({
76
+ method: HttpMethod.GET,
77
+ url: `${baseUrl}/api/v2/public/settings/tags`,
78
+ headers: {
79
+ Authorization: `Bearer ${token}`,
80
+ 'X-WorkBuddy-Version': '2026-01',
81
+ },
82
+ });
83
+ const items = response.body?.items || [];
84
+ return {
85
+ options: items.map((item) => ({
86
+ label: item.name,
87
+ value: item.id,
88
+ })),
89
+ };
90
+ },
25
91
  }),
26
- site: Property.Array({
92
+ site: Property.MultiSelectDropdown({
27
93
  displayName: 'Filter by Site',
28
- description: 'Only trigger for specific site IDs',
94
+ description: 'Only trigger for specific site',
29
95
  required: false,
96
+ auth: workbuddyAuth,
97
+ refreshers: [],
98
+ options: async ({ auth }) => {
99
+ const authValue = auth as unknown as { props: { baseUrl: string; clientId: string; clientSecret: string } };
100
+ const token = await getAccessToken(authValue);
101
+ const baseUrl = authValue.props.baseUrl;
102
+ const response = await httpClient.sendRequest<{ items: Array<{ id: string; name: string }> }>({
103
+ method: HttpMethod.GET,
104
+ url: `${baseUrl}/api/v2/public/sites`,
105
+ headers: {
106
+ Authorization: `Bearer ${token}`,
107
+ 'X-WorkBuddy-Version': '2026-01',
108
+ },
109
+ });
110
+ const items = response.body?.items || [];
111
+ return {
112
+ options: items.map((item) => ({
113
+ label: item.name,
114
+ value: item.id,
115
+ })),
116
+ };
117
+ },
30
118
  }),
31
- type: Property.Array({
119
+ type: Property.MultiSelectDropdown({
32
120
  displayName: 'Filter by Job Type',
33
- description: 'Only trigger for specific job type IDs',
121
+ description: 'Only trigger for specific job type',
34
122
  required: false,
123
+ auth: workbuddyAuth,
124
+ refreshers: [],
125
+ options: async ({ auth }) => {
126
+ const authValue = auth as unknown as { props: { baseUrl: string; clientId: string; clientSecret: string } };
127
+ const token = await getAccessToken(authValue);
128
+ const baseUrl = authValue.props.baseUrl;
129
+ const response = await httpClient.sendRequest<{ items: Array<{ id: string; name: string }> }>({
130
+ method: HttpMethod.GET,
131
+ url: `${baseUrl}/api/v2/public/settings/job-types`,
132
+ headers: {
133
+ Authorization: `Bearer ${token}`,
134
+ 'X-WorkBuddy-Version': '2026-01',
135
+ },
136
+ });
137
+ const items = response.body?.items || [];
138
+ return {
139
+ options: items.map((item) => ({
140
+ label: item.name,
141
+ value: item.id,
142
+ })),
143
+ };
144
+ },
35
145
  }),
36
- priority: Property.Array({
146
+ priority: Property.MultiSelectDropdown({
37
147
  displayName: 'Filter by Priority',
38
- description: 'Only trigger for specific priority IDs',
148
+ description: 'Only trigger for specific priority',
39
149
  required: false,
150
+ auth: workbuddyAuth,
151
+ refreshers: [],
152
+ options: async ({ auth }) => {
153
+ const authValue = auth as unknown as { props: { baseUrl: string; clientId: string; clientSecret: string } };
154
+ const token = await getAccessToken(authValue);
155
+ const baseUrl = authValue.props.baseUrl;
156
+ const response = await httpClient.sendRequest<{ items: Array<{ id: string; name: string }> }>({
157
+ method: HttpMethod.GET,
158
+ url: `${baseUrl}/api/v2/public/settings/priorities`,
159
+ headers: {
160
+ Authorization: `Bearer ${token}`,
161
+ 'X-WorkBuddy-Version': '2026-01',
162
+ },
163
+ });
164
+ const items = response.body?.items || [];
165
+ return {
166
+ options: items.map((item) => ({
167
+ label: item.name,
168
+ value: item.id,
169
+ })),
170
+ };
171
+ },
40
172
  }),
41
- owner: Property.Array({
173
+ owner: Property.MultiSelectDropdown({
42
174
  displayName: 'Filter by Owner',
43
- description: 'Only trigger for specific owner IDs',
175
+ description: 'Only trigger for specific owner',
44
176
  required: false,
177
+ auth: workbuddyAuth,
178
+ refreshers: [],
179
+ options: async ({ auth }) => {
180
+ const authValue = auth as unknown as { props: { baseUrl: string; clientId: string; clientSecret: string } };
181
+ const token = await getAccessToken(authValue);
182
+ const baseUrl = authValue.props.baseUrl;
183
+ const response = await httpClient.sendRequest<{ items: Array<{ id: string; name: string }> }>({
184
+ method: HttpMethod.GET,
185
+ url: `${baseUrl}/api/v2/public/employees`,
186
+ headers: {
187
+ Authorization: `Bearer ${token}`,
188
+ 'X-WorkBuddy-Version': '2026-01',
189
+ },
190
+ });
191
+ const items = response.body?.items || [];
192
+ return {
193
+ options: items.map((item) => ({
194
+ label: item.name,
195
+ value: item.id,
196
+ })),
197
+ };
198
+ },
45
199
  }),
46
- zone: Property.Array({
200
+ zone: Property.MultiSelectDropdown({
47
201
  displayName: 'Filter by Zone',
48
- description: 'Only trigger for specific zone IDs',
202
+ description: 'Only trigger for specific zone',
49
203
  required: false,
204
+ auth: workbuddyAuth,
205
+ refreshers: [],
206
+ options: async ({ auth }) => {
207
+ const authValue = auth as unknown as { props: { baseUrl: string; clientId: string; clientSecret: string } };
208
+ const token = await getAccessToken(authValue);
209
+ const baseUrl = authValue.props.baseUrl;
210
+ const response = await httpClient.sendRequest<{ items: Array<{ id: string; name: string }> }>({
211
+ method: HttpMethod.GET,
212
+ url: `${baseUrl}/api/v2/public/settings/zones`,
213
+ headers: {
214
+ Authorization: `Bearer ${token}`,
215
+ 'X-WorkBuddy-Version': '2026-01',
216
+ },
217
+ });
218
+ const items = response.body?.items || [];
219
+ return {
220
+ options: items.map((item) => ({
221
+ label: item.name,
222
+ value: item.id,
223
+ })),
224
+ };
225
+ },
50
226
  }),
51
227
  status: Property.StaticMultiSelectDropdown({
52
228
  displayName: 'Filter by Status',
@@ -64,39 +240,46 @@ export const job_created_trigger = createTrigger({
64
240
  }),
65
241
  },
66
242
  sampleData: {
67
- job: {
68
- id: '507f1f77bcf86cd799439011',
69
- mode: 'job',
70
- jobNumber: 'J10001',
71
- description: 'Sample job description',
72
- status: 'Open',
73
- source: 'web',
74
- createdAt: '2026-03-05T10:00:00.000Z',
75
- updatedAt: '2026-03-05T10:00:00.000Z',
76
- startDate: '2026-03-05T10:00:00.000Z',
77
- dueDate: '2026-03-15T10:00:00.000Z',
78
- completedDate: null,
79
- customer: { id: '507f1f77bcf86cd799439011', name: 'Acme Corp' },
80
- customerPO: 'PO-1234',
81
- customerWO: 'WO-5678',
82
- owner: { id: '507f1f77bcf86cd799439011', name: 'John Smith' },
83
- labels: [{ id: '507f1f77bcf86cd799439011', name: 'Urgent' }],
84
- zones: [{ id: '507f1f77bcf86cd799439011', name: 'North' }],
85
- site: {
243
+ id: 'whd_019ceacb-232b-764f-8dfd-748e1a226de2',
244
+ event: 'Job Created',
245
+ action: 'create',
246
+ createdAt: '2026-03-14T05:21:47.307Z',
247
+ webhookTimestamp: 1773465707307,
248
+ data: {
249
+ job: {
86
250
  id: '507f1f77bcf86cd799439011',
87
- name: 'Main Office',
88
- address: {
89
- street: '123 Main St',
90
- suburb: 'Sydney',
91
- state: 'NSW',
92
- postcode: '2000',
93
- country: 'Australia',
94
- formatted: '123 Main St, Sydney NSW 2000',
251
+ mode: 'job',
252
+ jobNumber: 'J10001',
253
+ description: 'Sample job description',
254
+ status: 'Open',
255
+ source: 'web',
256
+ createdAt: '2026-03-05T10:00:00.000Z',
257
+ updatedAt: '2026-03-05T10:00:00.000Z',
258
+ startDate: '2026-03-05T10:00:00.000Z',
259
+ dueDate: '2026-03-15T10:00:00.000Z',
260
+ completedDate: null,
261
+ customer: { id: '507f1f77bcf86cd799439011', name: 'Acme Corp' },
262
+ customerPO: 'PO-1234',
263
+ customerWO: 'WO-5678',
264
+ owner: { id: '507f1f77bcf86cd799439011', name: 'John Smith' },
265
+ labels: [{ id: '507f1f77bcf86cd799439011', name: 'Urgent' }],
266
+ zones: [{ id: '507f1f77bcf86cd799439011', name: 'North' }],
267
+ site: {
268
+ id: '507f1f77bcf86cd799439011',
269
+ name: 'Main Office',
270
+ address: {
271
+ street: '123 Main St',
272
+ suburb: 'Sydney',
273
+ state: 'NSW',
274
+ postcode: '2000',
275
+ country: 'Australia',
276
+ formatted: '123 Main St, Sydney NSW 2000',
277
+ },
95
278
  },
279
+ priority: { id: '507f1f77bcf86cd799439011', name: 'High' },
280
+ type: { id: '507f1f77bcf86cd799439011', name: 'Maintenance' },
281
+ billingCompany: { id: '507f1f77bcf86cd799439011', name: 'Acme Corp' },
96
282
  },
97
- priority: { id: '507f1f77bcf86cd799439011', name: 'High' },
98
- type: { id: '507f1f77bcf86cd799439011', name: 'Maintenance' },
99
- billingCompany: { id: '507f1f77bcf86cd799439011', name: 'Acme Corp' },
100
283
  },
101
284
  },
102
285
  type: TriggerStrategy.WEBHOOK,
@@ -116,7 +299,7 @@ export const job_created_trigger = createTrigger({
116
299
  if (context.propsValue.owner?.length) filters.owner = context.propsValue.owner;
117
300
  if (context.propsValue.zone?.length) filters.zone = context.propsValue.zone;
118
301
  if (context.propsValue.status?.length) filters.status = context.propsValue.status.map((v: string) => JSON.parse(v));
119
- // Register webhook with WorkBuddy v2 API (server handles upsert - reactivates if exists)
302
+ // Register webhook with WorkBuddy v2 API
120
303
  const response = await httpClient.sendRequest<{ data: { id: string } }>({
121
304
  method: HttpMethod.POST,
122
305
  url: `${baseUrl}/api/v2/public/webhooks`,
@@ -148,18 +331,15 @@ export const job_created_trigger = createTrigger({
148
331
  const webhookId = await context.store.get<string>('webhookId');
149
332
 
150
333
  if (webhookId) {
151
- // Pause webhook (server keeps it for potential reactivation)
334
+ // Delete webhook to avoid stale subscriptions causing duplicate trigger deliveries
152
335
  await httpClient.sendRequest({
153
- method: HttpMethod.PATCH,
336
+ method: HttpMethod.DELETE,
154
337
  url: `${baseUrl}/api/v2/public/webhooks/${webhookId}`,
155
338
  headers: {
156
339
  Authorization: `Bearer ${token}`,
157
340
  'Content-Type': 'application/json',
158
341
  'X-WorkBuddy-Version': '2026-01',
159
342
  },
160
- body: {
161
- status: 'paused',
162
- },
163
343
  });
164
344
  }
165
345
  },
@@ -175,45 +355,221 @@ export const job_updated_trigger = createTrigger({
175
355
  displayName: 'Job Updated',
176
356
  description: 'Triggered when a job is updated',
177
357
  props: {
178
- customer: Property.Array({
358
+ customer: Property.MultiSelectDropdown({
179
359
  displayName: 'Filter by Customer',
180
- description: 'Only trigger for specific customer IDs',
360
+ description: 'Only trigger for specific customer',
181
361
  required: false,
362
+ auth: workbuddyAuth,
363
+ refreshers: [],
364
+ options: async ({ auth }) => {
365
+ const authValue = auth as unknown as { props: { baseUrl: string; clientId: string; clientSecret: string } };
366
+ const token = await getAccessToken(authValue);
367
+ const baseUrl = authValue.props.baseUrl;
368
+ const response = await httpClient.sendRequest<{ items: Array<{ id: string; name: string }> }>({
369
+ method: HttpMethod.GET,
370
+ url: `${baseUrl}/api/v2/public/customers`,
371
+ headers: {
372
+ Authorization: `Bearer ${token}`,
373
+ 'X-WorkBuddy-Version': '2026-01',
374
+ },
375
+ });
376
+ const items = response.body?.items || [];
377
+ return {
378
+ options: items.map((item) => ({
379
+ label: item.name,
380
+ value: item.id,
381
+ })),
382
+ };
383
+ },
182
384
  }),
183
- billingCompany: Property.Array({
385
+ billingCompany: Property.MultiSelectDropdown({
184
386
  displayName: 'Filter by Billing Company',
185
- description: 'Only trigger for specific billing company IDs',
387
+ description: 'Only trigger for specific billing company',
186
388
  required: false,
389
+ auth: workbuddyAuth,
390
+ refreshers: [],
391
+ options: async ({ auth }) => {
392
+ const authValue = auth as unknown as { props: { baseUrl: string; clientId: string; clientSecret: string } };
393
+ const token = await getAccessToken(authValue);
394
+ const baseUrl = authValue.props.baseUrl;
395
+ const response = await httpClient.sendRequest<{ items: Array<{ id: string; name: string }> }>({
396
+ method: HttpMethod.GET,
397
+ url: `${baseUrl}/api/v2/public/companies`,
398
+ headers: {
399
+ Authorization: `Bearer ${token}`,
400
+ 'X-WorkBuddy-Version': '2026-01',
401
+ },
402
+ });
403
+ const items = response.body?.items || [];
404
+ return {
405
+ options: items.map((item) => ({
406
+ label: item.name,
407
+ value: item.id,
408
+ })),
409
+ };
410
+ },
187
411
  }),
188
- tag: Property.Array({
412
+ tag: Property.MultiSelectDropdown({
189
413
  displayName: 'Filter by Tags',
190
- description: 'Only trigger for specific tags IDs',
414
+ description: 'Only trigger for specific tags',
191
415
  required: false,
416
+ auth: workbuddyAuth,
417
+ refreshers: [],
418
+ options: async ({ auth }) => {
419
+ const authValue = auth as unknown as { props: { baseUrl: string; clientId: string; clientSecret: string } };
420
+ const token = await getAccessToken(authValue);
421
+ const baseUrl = authValue.props.baseUrl;
422
+ const response = await httpClient.sendRequest<{ items: Array<{ id: string; name: string }> }>({
423
+ method: HttpMethod.GET,
424
+ url: `${baseUrl}/api/v2/public/settings/tags`,
425
+ headers: {
426
+ Authorization: `Bearer ${token}`,
427
+ 'X-WorkBuddy-Version': '2026-01',
428
+ },
429
+ });
430
+ const items = response.body?.items || [];
431
+ return {
432
+ options: items.map((item) => ({
433
+ label: item.name,
434
+ value: item.id,
435
+ })),
436
+ };
437
+ },
192
438
  }),
193
- site: Property.Array({
439
+ site: Property.MultiSelectDropdown({
194
440
  displayName: 'Filter by Site',
195
- description: 'Only trigger for specific site IDs',
441
+ description: 'Only trigger for specific site',
196
442
  required: false,
443
+ auth: workbuddyAuth,
444
+ refreshers: [],
445
+ options: async ({ auth }) => {
446
+ const authValue = auth as unknown as { props: { baseUrl: string; clientId: string; clientSecret: string } };
447
+ const token = await getAccessToken(authValue);
448
+ const baseUrl = authValue.props.baseUrl;
449
+ const response = await httpClient.sendRequest<{ items: Array<{ id: string; name: string }> }>({
450
+ method: HttpMethod.GET,
451
+ url: `${baseUrl}/api/v2/public/sites`,
452
+ headers: {
453
+ Authorization: `Bearer ${token}`,
454
+ 'X-WorkBuddy-Version': '2026-01',
455
+ },
456
+ });
457
+ const items = response.body?.items || [];
458
+ return {
459
+ options: items.map((item) => ({
460
+ label: item.name,
461
+ value: item.id,
462
+ })),
463
+ };
464
+ },
197
465
  }),
198
- type: Property.Array({
466
+ type: Property.MultiSelectDropdown({
199
467
  displayName: 'Filter by Job Type',
200
- description: 'Only trigger for specific job type IDs',
468
+ description: 'Only trigger for specific job type',
201
469
  required: false,
470
+ auth: workbuddyAuth,
471
+ refreshers: [],
472
+ options: async ({ auth }) => {
473
+ const authValue = auth as unknown as { props: { baseUrl: string; clientId: string; clientSecret: string } };
474
+ const token = await getAccessToken(authValue);
475
+ const baseUrl = authValue.props.baseUrl;
476
+ const response = await httpClient.sendRequest<{ items: Array<{ id: string; name: string }> }>({
477
+ method: HttpMethod.GET,
478
+ url: `${baseUrl}/api/v2/public/settings/job-types`,
479
+ headers: {
480
+ Authorization: `Bearer ${token}`,
481
+ 'X-WorkBuddy-Version': '2026-01',
482
+ },
483
+ });
484
+ const items = response.body?.items || [];
485
+ return {
486
+ options: items.map((item) => ({
487
+ label: item.name,
488
+ value: item.id,
489
+ })),
490
+ };
491
+ },
202
492
  }),
203
- priority: Property.Array({
493
+ priority: Property.MultiSelectDropdown({
204
494
  displayName: 'Filter by Priority',
205
- description: 'Only trigger for specific priority IDs',
495
+ description: 'Only trigger for specific priority',
206
496
  required: false,
497
+ auth: workbuddyAuth,
498
+ refreshers: [],
499
+ options: async ({ auth }) => {
500
+ const authValue = auth as unknown as { props: { baseUrl: string; clientId: string; clientSecret: string } };
501
+ const token = await getAccessToken(authValue);
502
+ const baseUrl = authValue.props.baseUrl;
503
+ const response = await httpClient.sendRequest<{ items: Array<{ id: string; name: string }> }>({
504
+ method: HttpMethod.GET,
505
+ url: `${baseUrl}/api/v2/public/settings/priorities`,
506
+ headers: {
507
+ Authorization: `Bearer ${token}`,
508
+ 'X-WorkBuddy-Version': '2026-01',
509
+ },
510
+ });
511
+ const items = response.body?.items || [];
512
+ return {
513
+ options: items.map((item) => ({
514
+ label: item.name,
515
+ value: item.id,
516
+ })),
517
+ };
518
+ },
207
519
  }),
208
- owner: Property.Array({
520
+ owner: Property.MultiSelectDropdown({
209
521
  displayName: 'Filter by Owner',
210
- description: 'Only trigger for specific owner IDs',
522
+ description: 'Only trigger for specific owner',
211
523
  required: false,
524
+ auth: workbuddyAuth,
525
+ refreshers: [],
526
+ options: async ({ auth }) => {
527
+ const authValue = auth as unknown as { props: { baseUrl: string; clientId: string; clientSecret: string } };
528
+ const token = await getAccessToken(authValue);
529
+ const baseUrl = authValue.props.baseUrl;
530
+ const response = await httpClient.sendRequest<{ items: Array<{ id: string; name: string }> }>({
531
+ method: HttpMethod.GET,
532
+ url: `${baseUrl}/api/v2/public/employees`,
533
+ headers: {
534
+ Authorization: `Bearer ${token}`,
535
+ 'X-WorkBuddy-Version': '2026-01',
536
+ },
537
+ });
538
+ const items = response.body?.items || [];
539
+ return {
540
+ options: items.map((item) => ({
541
+ label: item.name,
542
+ value: item.id,
543
+ })),
544
+ };
545
+ },
212
546
  }),
213
- zone: Property.Array({
547
+ zone: Property.MultiSelectDropdown({
214
548
  displayName: 'Filter by Zone',
215
- description: 'Only trigger for specific zone IDs',
549
+ description: 'Only trigger for specific zone',
216
550
  required: false,
551
+ auth: workbuddyAuth,
552
+ refreshers: [],
553
+ options: async ({ auth }) => {
554
+ const authValue = auth as unknown as { props: { baseUrl: string; clientId: string; clientSecret: string } };
555
+ const token = await getAccessToken(authValue);
556
+ const baseUrl = authValue.props.baseUrl;
557
+ const response = await httpClient.sendRequest<{ items: Array<{ id: string; name: string }> }>({
558
+ method: HttpMethod.GET,
559
+ url: `${baseUrl}/api/v2/public/settings/zones`,
560
+ headers: {
561
+ Authorization: `Bearer ${token}`,
562
+ 'X-WorkBuddy-Version': '2026-01',
563
+ },
564
+ });
565
+ const items = response.body?.items || [];
566
+ return {
567
+ options: items.map((item) => ({
568
+ label: item.name,
569
+ value: item.id,
570
+ })),
571
+ };
572
+ },
217
573
  }),
218
574
  status: Property.StaticMultiSelectDropdown({
219
575
  displayName: 'Filter by Status',
@@ -231,39 +587,46 @@ export const job_updated_trigger = createTrigger({
231
587
  }),
232
588
  },
233
589
  sampleData: {
234
- job: {
235
- id: '507f1f77bcf86cd799439011',
236
- mode: 'job',
237
- jobNumber: 'J10001',
238
- description: 'Sample job description',
239
- status: 'Open',
240
- source: 'web',
241
- createdAt: '2026-03-05T10:00:00.000Z',
242
- updatedAt: '2026-03-05T10:00:00.000Z',
243
- startDate: '2026-03-05T10:00:00.000Z',
244
- dueDate: '2026-03-15T10:00:00.000Z',
245
- completedDate: null,
246
- customer: { id: '507f1f77bcf86cd799439011', name: 'Acme Corp' },
247
- customerPO: 'PO-1234',
248
- customerWO: 'WO-5678',
249
- owner: { id: '507f1f77bcf86cd799439011', name: 'John Smith' },
250
- labels: [{ id: '507f1f77bcf86cd799439011', name: 'Urgent' }],
251
- zones: [{ id: '507f1f77bcf86cd799439011', name: 'North' }],
252
- site: {
590
+ id: 'whd_019ceacb-232b-764f-8dfd-748e1a226de2',
591
+ event: 'Job Updated',
592
+ action: 'update',
593
+ createdAt: '2026-03-14T05:21:47.307Z',
594
+ webhookTimestamp: 1773465707307,
595
+ data: {
596
+ job: {
253
597
  id: '507f1f77bcf86cd799439011',
254
- name: 'Main Office',
255
- address: {
256
- street: '123 Main St',
257
- suburb: 'Sydney',
258
- state: 'NSW',
259
- postcode: '2000',
260
- country: 'Australia',
261
- formatted: '123 Main St, Sydney NSW 2000',
598
+ mode: 'job',
599
+ jobNumber: 'J10001',
600
+ description: 'Sample job description',
601
+ status: 'Open',
602
+ source: 'web',
603
+ createdAt: '2026-03-05T10:00:00.000Z',
604
+ updatedAt: '2026-03-05T10:00:00.000Z',
605
+ startDate: '2026-03-05T10:00:00.000Z',
606
+ dueDate: '2026-03-15T10:00:00.000Z',
607
+ completedDate: null,
608
+ customer: { id: '507f1f77bcf86cd799439011', name: 'Acme Corp' },
609
+ customerPO: 'PO-1234',
610
+ customerWO: 'WO-5678',
611
+ owner: { id: '507f1f77bcf86cd799439011', name: 'John Smith' },
612
+ labels: [{ id: '507f1f77bcf86cd799439011', name: 'Urgent' }],
613
+ zones: [{ id: '507f1f77bcf86cd799439011', name: 'North' }],
614
+ site: {
615
+ id: '507f1f77bcf86cd799439011',
616
+ name: 'Main Office',
617
+ address: {
618
+ street: '123 Main St',
619
+ suburb: 'Sydney',
620
+ state: 'NSW',
621
+ postcode: '2000',
622
+ country: 'Australia',
623
+ formatted: '123 Main St, Sydney NSW 2000',
624
+ },
262
625
  },
626
+ priority: { id: '507f1f77bcf86cd799439011', name: 'High' },
627
+ type: { id: '507f1f77bcf86cd799439011', name: 'Maintenance' },
628
+ billingCompany: { id: '507f1f77bcf86cd799439011', name: 'Acme Corp' },
263
629
  },
264
- priority: { id: '507f1f77bcf86cd799439011', name: 'High' },
265
- type: { id: '507f1f77bcf86cd799439011', name: 'Maintenance' },
266
- billingCompany: { id: '507f1f77bcf86cd799439011', name: 'Acme Corp' },
267
630
  },
268
631
  },
269
632
  type: TriggerStrategy.WEBHOOK,
@@ -283,7 +646,7 @@ export const job_updated_trigger = createTrigger({
283
646
  if (context.propsValue.owner?.length) filters.owner = context.propsValue.owner;
284
647
  if (context.propsValue.zone?.length) filters.zone = context.propsValue.zone;
285
648
  if (context.propsValue.status?.length) filters.status = context.propsValue.status.map((v: string) => JSON.parse(v));
286
- // Register webhook with WorkBuddy v2 API (server handles upsert - reactivates if exists)
649
+ // Register webhook with WorkBuddy v2 API
287
650
  const response = await httpClient.sendRequest<{ data: { id: string } }>({
288
651
  method: HttpMethod.POST,
289
652
  url: `${baseUrl}/api/v2/public/webhooks`,
@@ -315,18 +678,15 @@ export const job_updated_trigger = createTrigger({
315
678
  const webhookId = await context.store.get<string>('webhookId');
316
679
 
317
680
  if (webhookId) {
318
- // Pause webhook (server keeps it for potential reactivation)
681
+ // Delete webhook to avoid stale subscriptions causing duplicate trigger deliveries
319
682
  await httpClient.sendRequest({
320
- method: HttpMethod.PATCH,
683
+ method: HttpMethod.DELETE,
321
684
  url: `${baseUrl}/api/v2/public/webhooks/${webhookId}`,
322
685
  headers: {
323
686
  Authorization: `Bearer ${token}`,
324
687
  'Content-Type': 'application/json',
325
688
  'X-WorkBuddy-Version': '2026-01',
326
689
  },
327
- body: {
328
- status: 'paused',
329
- },
330
690
  });
331
691
  }
332
692
  },
@@ -342,45 +702,221 @@ export const job_status_changed_trigger = createTrigger({
342
702
  displayName: 'Job Status Changed',
343
703
  description: 'Triggered when a job status changes',
344
704
  props: {
345
- customer: Property.Array({
705
+ customer: Property.MultiSelectDropdown({
346
706
  displayName: 'Filter by Customer',
347
- description: 'Only trigger for specific customer IDs',
707
+ description: 'Only trigger for specific customer',
348
708
  required: false,
709
+ auth: workbuddyAuth,
710
+ refreshers: [],
711
+ options: async ({ auth }) => {
712
+ const authValue = auth as unknown as { props: { baseUrl: string; clientId: string; clientSecret: string } };
713
+ const token = await getAccessToken(authValue);
714
+ const baseUrl = authValue.props.baseUrl;
715
+ const response = await httpClient.sendRequest<{ items: Array<{ id: string; name: string }> }>({
716
+ method: HttpMethod.GET,
717
+ url: `${baseUrl}/api/v2/public/customers`,
718
+ headers: {
719
+ Authorization: `Bearer ${token}`,
720
+ 'X-WorkBuddy-Version': '2026-01',
721
+ },
722
+ });
723
+ const items = response.body?.items || [];
724
+ return {
725
+ options: items.map((item) => ({
726
+ label: item.name,
727
+ value: item.id,
728
+ })),
729
+ };
730
+ },
349
731
  }),
350
- billingCompany: Property.Array({
732
+ billingCompany: Property.MultiSelectDropdown({
351
733
  displayName: 'Filter by Billing Company',
352
- description: 'Only trigger for specific billing company IDs',
734
+ description: 'Only trigger for specific billing company',
353
735
  required: false,
736
+ auth: workbuddyAuth,
737
+ refreshers: [],
738
+ options: async ({ auth }) => {
739
+ const authValue = auth as unknown as { props: { baseUrl: string; clientId: string; clientSecret: string } };
740
+ const token = await getAccessToken(authValue);
741
+ const baseUrl = authValue.props.baseUrl;
742
+ const response = await httpClient.sendRequest<{ items: Array<{ id: string; name: string }> }>({
743
+ method: HttpMethod.GET,
744
+ url: `${baseUrl}/api/v2/public/companies`,
745
+ headers: {
746
+ Authorization: `Bearer ${token}`,
747
+ 'X-WorkBuddy-Version': '2026-01',
748
+ },
749
+ });
750
+ const items = response.body?.items || [];
751
+ return {
752
+ options: items.map((item) => ({
753
+ label: item.name,
754
+ value: item.id,
755
+ })),
756
+ };
757
+ },
354
758
  }),
355
- tag: Property.Array({
759
+ tag: Property.MultiSelectDropdown({
356
760
  displayName: 'Filter by Tags',
357
- description: 'Only trigger for specific tags IDs',
761
+ description: 'Only trigger for specific tags',
358
762
  required: false,
763
+ auth: workbuddyAuth,
764
+ refreshers: [],
765
+ options: async ({ auth }) => {
766
+ const authValue = auth as unknown as { props: { baseUrl: string; clientId: string; clientSecret: string } };
767
+ const token = await getAccessToken(authValue);
768
+ const baseUrl = authValue.props.baseUrl;
769
+ const response = await httpClient.sendRequest<{ items: Array<{ id: string; name: string }> }>({
770
+ method: HttpMethod.GET,
771
+ url: `${baseUrl}/api/v2/public/settings/tags`,
772
+ headers: {
773
+ Authorization: `Bearer ${token}`,
774
+ 'X-WorkBuddy-Version': '2026-01',
775
+ },
776
+ });
777
+ const items = response.body?.items || [];
778
+ return {
779
+ options: items.map((item) => ({
780
+ label: item.name,
781
+ value: item.id,
782
+ })),
783
+ };
784
+ },
359
785
  }),
360
- site: Property.Array({
786
+ site: Property.MultiSelectDropdown({
361
787
  displayName: 'Filter by Site',
362
- description: 'Only trigger for specific site IDs',
788
+ description: 'Only trigger for specific site',
363
789
  required: false,
790
+ auth: workbuddyAuth,
791
+ refreshers: [],
792
+ options: async ({ auth }) => {
793
+ const authValue = auth as unknown as { props: { baseUrl: string; clientId: string; clientSecret: string } };
794
+ const token = await getAccessToken(authValue);
795
+ const baseUrl = authValue.props.baseUrl;
796
+ const response = await httpClient.sendRequest<{ items: Array<{ id: string; name: string }> }>({
797
+ method: HttpMethod.GET,
798
+ url: `${baseUrl}/api/v2/public/sites`,
799
+ headers: {
800
+ Authorization: `Bearer ${token}`,
801
+ 'X-WorkBuddy-Version': '2026-01',
802
+ },
803
+ });
804
+ const items = response.body?.items || [];
805
+ return {
806
+ options: items.map((item) => ({
807
+ label: item.name,
808
+ value: item.id,
809
+ })),
810
+ };
811
+ },
364
812
  }),
365
- type: Property.Array({
813
+ type: Property.MultiSelectDropdown({
366
814
  displayName: 'Filter by Job Type',
367
- description: 'Only trigger for specific job type IDs',
815
+ description: 'Only trigger for specific job type',
368
816
  required: false,
817
+ auth: workbuddyAuth,
818
+ refreshers: [],
819
+ options: async ({ auth }) => {
820
+ const authValue = auth as unknown as { props: { baseUrl: string; clientId: string; clientSecret: string } };
821
+ const token = await getAccessToken(authValue);
822
+ const baseUrl = authValue.props.baseUrl;
823
+ const response = await httpClient.sendRequest<{ items: Array<{ id: string; name: string }> }>({
824
+ method: HttpMethod.GET,
825
+ url: `${baseUrl}/api/v2/public/settings/job-types`,
826
+ headers: {
827
+ Authorization: `Bearer ${token}`,
828
+ 'X-WorkBuddy-Version': '2026-01',
829
+ },
830
+ });
831
+ const items = response.body?.items || [];
832
+ return {
833
+ options: items.map((item) => ({
834
+ label: item.name,
835
+ value: item.id,
836
+ })),
837
+ };
838
+ },
369
839
  }),
370
- priority: Property.Array({
840
+ priority: Property.MultiSelectDropdown({
371
841
  displayName: 'Filter by Priority',
372
- description: 'Only trigger for specific priority IDs',
842
+ description: 'Only trigger for specific priority',
373
843
  required: false,
844
+ auth: workbuddyAuth,
845
+ refreshers: [],
846
+ options: async ({ auth }) => {
847
+ const authValue = auth as unknown as { props: { baseUrl: string; clientId: string; clientSecret: string } };
848
+ const token = await getAccessToken(authValue);
849
+ const baseUrl = authValue.props.baseUrl;
850
+ const response = await httpClient.sendRequest<{ items: Array<{ id: string; name: string }> }>({
851
+ method: HttpMethod.GET,
852
+ url: `${baseUrl}/api/v2/public/settings/priorities`,
853
+ headers: {
854
+ Authorization: `Bearer ${token}`,
855
+ 'X-WorkBuddy-Version': '2026-01',
856
+ },
857
+ });
858
+ const items = response.body?.items || [];
859
+ return {
860
+ options: items.map((item) => ({
861
+ label: item.name,
862
+ value: item.id,
863
+ })),
864
+ };
865
+ },
374
866
  }),
375
- owner: Property.Array({
867
+ owner: Property.MultiSelectDropdown({
376
868
  displayName: 'Filter by Owner',
377
- description: 'Only trigger for specific owner IDs',
869
+ description: 'Only trigger for specific owner',
378
870
  required: false,
871
+ auth: workbuddyAuth,
872
+ refreshers: [],
873
+ options: async ({ auth }) => {
874
+ const authValue = auth as unknown as { props: { baseUrl: string; clientId: string; clientSecret: string } };
875
+ const token = await getAccessToken(authValue);
876
+ const baseUrl = authValue.props.baseUrl;
877
+ const response = await httpClient.sendRequest<{ items: Array<{ id: string; name: string }> }>({
878
+ method: HttpMethod.GET,
879
+ url: `${baseUrl}/api/v2/public/employees`,
880
+ headers: {
881
+ Authorization: `Bearer ${token}`,
882
+ 'X-WorkBuddy-Version': '2026-01',
883
+ },
884
+ });
885
+ const items = response.body?.items || [];
886
+ return {
887
+ options: items.map((item) => ({
888
+ label: item.name,
889
+ value: item.id,
890
+ })),
891
+ };
892
+ },
379
893
  }),
380
- zone: Property.Array({
894
+ zone: Property.MultiSelectDropdown({
381
895
  displayName: 'Filter by Zone',
382
- description: 'Only trigger for specific zone IDs',
896
+ description: 'Only trigger for specific zone',
383
897
  required: false,
898
+ auth: workbuddyAuth,
899
+ refreshers: [],
900
+ options: async ({ auth }) => {
901
+ const authValue = auth as unknown as { props: { baseUrl: string; clientId: string; clientSecret: string } };
902
+ const token = await getAccessToken(authValue);
903
+ const baseUrl = authValue.props.baseUrl;
904
+ const response = await httpClient.sendRequest<{ items: Array<{ id: string; name: string }> }>({
905
+ method: HttpMethod.GET,
906
+ url: `${baseUrl}/api/v2/public/settings/zones`,
907
+ headers: {
908
+ Authorization: `Bearer ${token}`,
909
+ 'X-WorkBuddy-Version': '2026-01',
910
+ },
911
+ });
912
+ const items = response.body?.items || [];
913
+ return {
914
+ options: items.map((item) => ({
915
+ label: item.name,
916
+ value: item.id,
917
+ })),
918
+ };
919
+ },
384
920
  }),
385
921
  status: Property.StaticMultiSelectDropdown({
386
922
  displayName: 'Filter by Status',
@@ -398,39 +934,46 @@ export const job_status_changed_trigger = createTrigger({
398
934
  }),
399
935
  },
400
936
  sampleData: {
401
- job: {
402
- id: '507f1f77bcf86cd799439011',
403
- mode: 'job',
404
- jobNumber: 'J10001',
405
- description: 'Sample job description',
406
- status: 'Open',
407
- source: 'web',
408
- createdAt: '2026-03-05T10:00:00.000Z',
409
- updatedAt: '2026-03-05T10:00:00.000Z',
410
- startDate: '2026-03-05T10:00:00.000Z',
411
- dueDate: '2026-03-15T10:00:00.000Z',
412
- completedDate: null,
413
- customer: { id: '507f1f77bcf86cd799439011', name: 'Acme Corp' },
414
- customerPO: 'PO-1234',
415
- customerWO: 'WO-5678',
416
- owner: { id: '507f1f77bcf86cd799439011', name: 'John Smith' },
417
- labels: [{ id: '507f1f77bcf86cd799439011', name: 'Urgent' }],
418
- zones: [{ id: '507f1f77bcf86cd799439011', name: 'North' }],
419
- site: {
937
+ id: 'whd_019ceacb-232b-764f-8dfd-748e1a226de2',
938
+ event: 'Job Status Changed',
939
+ action: 'update',
940
+ createdAt: '2026-03-14T05:21:47.307Z',
941
+ webhookTimestamp: 1773465707307,
942
+ data: {
943
+ job: {
420
944
  id: '507f1f77bcf86cd799439011',
421
- name: 'Main Office',
422
- address: {
423
- street: '123 Main St',
424
- suburb: 'Sydney',
425
- state: 'NSW',
426
- postcode: '2000',
427
- country: 'Australia',
428
- formatted: '123 Main St, Sydney NSW 2000',
945
+ mode: 'job',
946
+ jobNumber: 'J10001',
947
+ description: 'Sample job description',
948
+ status: 'Open',
949
+ source: 'web',
950
+ createdAt: '2026-03-05T10:00:00.000Z',
951
+ updatedAt: '2026-03-05T10:00:00.000Z',
952
+ startDate: '2026-03-05T10:00:00.000Z',
953
+ dueDate: '2026-03-15T10:00:00.000Z',
954
+ completedDate: null,
955
+ customer: { id: '507f1f77bcf86cd799439011', name: 'Acme Corp' },
956
+ customerPO: 'PO-1234',
957
+ customerWO: 'WO-5678',
958
+ owner: { id: '507f1f77bcf86cd799439011', name: 'John Smith' },
959
+ labels: [{ id: '507f1f77bcf86cd799439011', name: 'Urgent' }],
960
+ zones: [{ id: '507f1f77bcf86cd799439011', name: 'North' }],
961
+ site: {
962
+ id: '507f1f77bcf86cd799439011',
963
+ name: 'Main Office',
964
+ address: {
965
+ street: '123 Main St',
966
+ suburb: 'Sydney',
967
+ state: 'NSW',
968
+ postcode: '2000',
969
+ country: 'Australia',
970
+ formatted: '123 Main St, Sydney NSW 2000',
971
+ },
429
972
  },
973
+ priority: { id: '507f1f77bcf86cd799439011', name: 'High' },
974
+ type: { id: '507f1f77bcf86cd799439011', name: 'Maintenance' },
975
+ billingCompany: { id: '507f1f77bcf86cd799439011', name: 'Acme Corp' },
430
976
  },
431
- priority: { id: '507f1f77bcf86cd799439011', name: 'High' },
432
- type: { id: '507f1f77bcf86cd799439011', name: 'Maintenance' },
433
- billingCompany: { id: '507f1f77bcf86cd799439011', name: 'Acme Corp' },
434
977
  },
435
978
  },
436
979
  type: TriggerStrategy.WEBHOOK,
@@ -450,7 +993,7 @@ export const job_status_changed_trigger = createTrigger({
450
993
  if (context.propsValue.owner?.length) filters.owner = context.propsValue.owner;
451
994
  if (context.propsValue.zone?.length) filters.zone = context.propsValue.zone;
452
995
  if (context.propsValue.status?.length) filters.status = context.propsValue.status.map((v: string) => JSON.parse(v));
453
- // Register webhook with WorkBuddy v2 API (server handles upsert - reactivates if exists)
996
+ // Register webhook with WorkBuddy v2 API
454
997
  const response = await httpClient.sendRequest<{ data: { id: string } }>({
455
998
  method: HttpMethod.POST,
456
999
  url: `${baseUrl}/api/v2/public/webhooks`,
@@ -482,18 +1025,15 @@ export const job_status_changed_trigger = createTrigger({
482
1025
  const webhookId = await context.store.get<string>('webhookId');
483
1026
 
484
1027
  if (webhookId) {
485
- // Pause webhook (server keeps it for potential reactivation)
1028
+ // Delete webhook to avoid stale subscriptions causing duplicate trigger deliveries
486
1029
  await httpClient.sendRequest({
487
- method: HttpMethod.PATCH,
1030
+ method: HttpMethod.DELETE,
488
1031
  url: `${baseUrl}/api/v2/public/webhooks/${webhookId}`,
489
1032
  headers: {
490
1033
  Authorization: `Bearer ${token}`,
491
1034
  'Content-Type': 'application/json',
492
1035
  'X-WorkBuddy-Version': '2026-01',
493
1036
  },
494
- body: {
495
- status: 'paused',
496
- },
497
1037
  });
498
1038
  }
499
1039
  },
@@ -509,45 +1049,221 @@ export const job_deleted_trigger = createTrigger({
509
1049
  displayName: 'Job Deleted',
510
1050
  description: 'Triggered when a job is deleted',
511
1051
  props: {
512
- customer: Property.Array({
1052
+ customer: Property.MultiSelectDropdown({
513
1053
  displayName: 'Filter by Customer',
514
- description: 'Only trigger for specific customer IDs',
1054
+ description: 'Only trigger for specific customer',
515
1055
  required: false,
1056
+ auth: workbuddyAuth,
1057
+ refreshers: [],
1058
+ options: async ({ auth }) => {
1059
+ const authValue = auth as unknown as { props: { baseUrl: string; clientId: string; clientSecret: string } };
1060
+ const token = await getAccessToken(authValue);
1061
+ const baseUrl = authValue.props.baseUrl;
1062
+ const response = await httpClient.sendRequest<{ items: Array<{ id: string; name: string }> }>({
1063
+ method: HttpMethod.GET,
1064
+ url: `${baseUrl}/api/v2/public/customers`,
1065
+ headers: {
1066
+ Authorization: `Bearer ${token}`,
1067
+ 'X-WorkBuddy-Version': '2026-01',
1068
+ },
1069
+ });
1070
+ const items = response.body?.items || [];
1071
+ return {
1072
+ options: items.map((item) => ({
1073
+ label: item.name,
1074
+ value: item.id,
1075
+ })),
1076
+ };
1077
+ },
516
1078
  }),
517
- billingCompany: Property.Array({
1079
+ billingCompany: Property.MultiSelectDropdown({
518
1080
  displayName: 'Filter by Billing Company',
519
- description: 'Only trigger for specific billing company IDs',
1081
+ description: 'Only trigger for specific billing company',
520
1082
  required: false,
1083
+ auth: workbuddyAuth,
1084
+ refreshers: [],
1085
+ options: async ({ auth }) => {
1086
+ const authValue = auth as unknown as { props: { baseUrl: string; clientId: string; clientSecret: string } };
1087
+ const token = await getAccessToken(authValue);
1088
+ const baseUrl = authValue.props.baseUrl;
1089
+ const response = await httpClient.sendRequest<{ items: Array<{ id: string; name: string }> }>({
1090
+ method: HttpMethod.GET,
1091
+ url: `${baseUrl}/api/v2/public/companies`,
1092
+ headers: {
1093
+ Authorization: `Bearer ${token}`,
1094
+ 'X-WorkBuddy-Version': '2026-01',
1095
+ },
1096
+ });
1097
+ const items = response.body?.items || [];
1098
+ return {
1099
+ options: items.map((item) => ({
1100
+ label: item.name,
1101
+ value: item.id,
1102
+ })),
1103
+ };
1104
+ },
521
1105
  }),
522
- tag: Property.Array({
1106
+ tag: Property.MultiSelectDropdown({
523
1107
  displayName: 'Filter by Tags',
524
- description: 'Only trigger for specific tags IDs',
1108
+ description: 'Only trigger for specific tags',
525
1109
  required: false,
1110
+ auth: workbuddyAuth,
1111
+ refreshers: [],
1112
+ options: async ({ auth }) => {
1113
+ const authValue = auth as unknown as { props: { baseUrl: string; clientId: string; clientSecret: string } };
1114
+ const token = await getAccessToken(authValue);
1115
+ const baseUrl = authValue.props.baseUrl;
1116
+ const response = await httpClient.sendRequest<{ items: Array<{ id: string; name: string }> }>({
1117
+ method: HttpMethod.GET,
1118
+ url: `${baseUrl}/api/v2/public/settings/tags`,
1119
+ headers: {
1120
+ Authorization: `Bearer ${token}`,
1121
+ 'X-WorkBuddy-Version': '2026-01',
1122
+ },
1123
+ });
1124
+ const items = response.body?.items || [];
1125
+ return {
1126
+ options: items.map((item) => ({
1127
+ label: item.name,
1128
+ value: item.id,
1129
+ })),
1130
+ };
1131
+ },
526
1132
  }),
527
- site: Property.Array({
1133
+ site: Property.MultiSelectDropdown({
528
1134
  displayName: 'Filter by Site',
529
- description: 'Only trigger for specific site IDs',
1135
+ description: 'Only trigger for specific site',
530
1136
  required: false,
1137
+ auth: workbuddyAuth,
1138
+ refreshers: [],
1139
+ options: async ({ auth }) => {
1140
+ const authValue = auth as unknown as { props: { baseUrl: string; clientId: string; clientSecret: string } };
1141
+ const token = await getAccessToken(authValue);
1142
+ const baseUrl = authValue.props.baseUrl;
1143
+ const response = await httpClient.sendRequest<{ items: Array<{ id: string; name: string }> }>({
1144
+ method: HttpMethod.GET,
1145
+ url: `${baseUrl}/api/v2/public/sites`,
1146
+ headers: {
1147
+ Authorization: `Bearer ${token}`,
1148
+ 'X-WorkBuddy-Version': '2026-01',
1149
+ },
1150
+ });
1151
+ const items = response.body?.items || [];
1152
+ return {
1153
+ options: items.map((item) => ({
1154
+ label: item.name,
1155
+ value: item.id,
1156
+ })),
1157
+ };
1158
+ },
531
1159
  }),
532
- type: Property.Array({
1160
+ type: Property.MultiSelectDropdown({
533
1161
  displayName: 'Filter by Job Type',
534
- description: 'Only trigger for specific job type IDs',
1162
+ description: 'Only trigger for specific job type',
535
1163
  required: false,
1164
+ auth: workbuddyAuth,
1165
+ refreshers: [],
1166
+ options: async ({ auth }) => {
1167
+ const authValue = auth as unknown as { props: { baseUrl: string; clientId: string; clientSecret: string } };
1168
+ const token = await getAccessToken(authValue);
1169
+ const baseUrl = authValue.props.baseUrl;
1170
+ const response = await httpClient.sendRequest<{ items: Array<{ id: string; name: string }> }>({
1171
+ method: HttpMethod.GET,
1172
+ url: `${baseUrl}/api/v2/public/settings/job-types`,
1173
+ headers: {
1174
+ Authorization: `Bearer ${token}`,
1175
+ 'X-WorkBuddy-Version': '2026-01',
1176
+ },
1177
+ });
1178
+ const items = response.body?.items || [];
1179
+ return {
1180
+ options: items.map((item) => ({
1181
+ label: item.name,
1182
+ value: item.id,
1183
+ })),
1184
+ };
1185
+ },
536
1186
  }),
537
- priority: Property.Array({
1187
+ priority: Property.MultiSelectDropdown({
538
1188
  displayName: 'Filter by Priority',
539
- description: 'Only trigger for specific priority IDs',
1189
+ description: 'Only trigger for specific priority',
540
1190
  required: false,
1191
+ auth: workbuddyAuth,
1192
+ refreshers: [],
1193
+ options: async ({ auth }) => {
1194
+ const authValue = auth as unknown as { props: { baseUrl: string; clientId: string; clientSecret: string } };
1195
+ const token = await getAccessToken(authValue);
1196
+ const baseUrl = authValue.props.baseUrl;
1197
+ const response = await httpClient.sendRequest<{ items: Array<{ id: string; name: string }> }>({
1198
+ method: HttpMethod.GET,
1199
+ url: `${baseUrl}/api/v2/public/settings/priorities`,
1200
+ headers: {
1201
+ Authorization: `Bearer ${token}`,
1202
+ 'X-WorkBuddy-Version': '2026-01',
1203
+ },
1204
+ });
1205
+ const items = response.body?.items || [];
1206
+ return {
1207
+ options: items.map((item) => ({
1208
+ label: item.name,
1209
+ value: item.id,
1210
+ })),
1211
+ };
1212
+ },
541
1213
  }),
542
- owner: Property.Array({
1214
+ owner: Property.MultiSelectDropdown({
543
1215
  displayName: 'Filter by Owner',
544
- description: 'Only trigger for specific owner IDs',
1216
+ description: 'Only trigger for specific owner',
545
1217
  required: false,
1218
+ auth: workbuddyAuth,
1219
+ refreshers: [],
1220
+ options: async ({ auth }) => {
1221
+ const authValue = auth as unknown as { props: { baseUrl: string; clientId: string; clientSecret: string } };
1222
+ const token = await getAccessToken(authValue);
1223
+ const baseUrl = authValue.props.baseUrl;
1224
+ const response = await httpClient.sendRequest<{ items: Array<{ id: string; name: string }> }>({
1225
+ method: HttpMethod.GET,
1226
+ url: `${baseUrl}/api/v2/public/employees`,
1227
+ headers: {
1228
+ Authorization: `Bearer ${token}`,
1229
+ 'X-WorkBuddy-Version': '2026-01',
1230
+ },
1231
+ });
1232
+ const items = response.body?.items || [];
1233
+ return {
1234
+ options: items.map((item) => ({
1235
+ label: item.name,
1236
+ value: item.id,
1237
+ })),
1238
+ };
1239
+ },
546
1240
  }),
547
- zone: Property.Array({
1241
+ zone: Property.MultiSelectDropdown({
548
1242
  displayName: 'Filter by Zone',
549
- description: 'Only trigger for specific zone IDs',
1243
+ description: 'Only trigger for specific zone',
550
1244
  required: false,
1245
+ auth: workbuddyAuth,
1246
+ refreshers: [],
1247
+ options: async ({ auth }) => {
1248
+ const authValue = auth as unknown as { props: { baseUrl: string; clientId: string; clientSecret: string } };
1249
+ const token = await getAccessToken(authValue);
1250
+ const baseUrl = authValue.props.baseUrl;
1251
+ const response = await httpClient.sendRequest<{ items: Array<{ id: string; name: string }> }>({
1252
+ method: HttpMethod.GET,
1253
+ url: `${baseUrl}/api/v2/public/settings/zones`,
1254
+ headers: {
1255
+ Authorization: `Bearer ${token}`,
1256
+ 'X-WorkBuddy-Version': '2026-01',
1257
+ },
1258
+ });
1259
+ const items = response.body?.items || [];
1260
+ return {
1261
+ options: items.map((item) => ({
1262
+ label: item.name,
1263
+ value: item.id,
1264
+ })),
1265
+ };
1266
+ },
551
1267
  }),
552
1268
  status: Property.StaticMultiSelectDropdown({
553
1269
  displayName: 'Filter by Status',
@@ -565,39 +1281,46 @@ export const job_deleted_trigger = createTrigger({
565
1281
  }),
566
1282
  },
567
1283
  sampleData: {
568
- job: {
569
- id: '507f1f77bcf86cd799439011',
570
- mode: 'job',
571
- jobNumber: 'J10001',
572
- description: 'Sample job description',
573
- status: 'Open',
574
- source: 'web',
575
- createdAt: '2026-03-05T10:00:00.000Z',
576
- updatedAt: '2026-03-05T10:00:00.000Z',
577
- startDate: '2026-03-05T10:00:00.000Z',
578
- dueDate: '2026-03-15T10:00:00.000Z',
579
- completedDate: null,
580
- customer: { id: '507f1f77bcf86cd799439011', name: 'Acme Corp' },
581
- customerPO: 'PO-1234',
582
- customerWO: 'WO-5678',
583
- owner: { id: '507f1f77bcf86cd799439011', name: 'John Smith' },
584
- labels: [{ id: '507f1f77bcf86cd799439011', name: 'Urgent' }],
585
- zones: [{ id: '507f1f77bcf86cd799439011', name: 'North' }],
586
- site: {
1284
+ id: 'whd_019ceacb-232b-764f-8dfd-748e1a226de2',
1285
+ event: 'Job Deleted',
1286
+ action: 'remove',
1287
+ createdAt: '2026-03-14T05:21:47.307Z',
1288
+ webhookTimestamp: 1773465707307,
1289
+ data: {
1290
+ job: {
587
1291
  id: '507f1f77bcf86cd799439011',
588
- name: 'Main Office',
589
- address: {
590
- street: '123 Main St',
591
- suburb: 'Sydney',
592
- state: 'NSW',
593
- postcode: '2000',
594
- country: 'Australia',
595
- formatted: '123 Main St, Sydney NSW 2000',
1292
+ mode: 'job',
1293
+ jobNumber: 'J10001',
1294
+ description: 'Sample job description',
1295
+ status: 'Open',
1296
+ source: 'web',
1297
+ createdAt: '2026-03-05T10:00:00.000Z',
1298
+ updatedAt: '2026-03-05T10:00:00.000Z',
1299
+ startDate: '2026-03-05T10:00:00.000Z',
1300
+ dueDate: '2026-03-15T10:00:00.000Z',
1301
+ completedDate: null,
1302
+ customer: { id: '507f1f77bcf86cd799439011', name: 'Acme Corp' },
1303
+ customerPO: 'PO-1234',
1304
+ customerWO: 'WO-5678',
1305
+ owner: { id: '507f1f77bcf86cd799439011', name: 'John Smith' },
1306
+ labels: [{ id: '507f1f77bcf86cd799439011', name: 'Urgent' }],
1307
+ zones: [{ id: '507f1f77bcf86cd799439011', name: 'North' }],
1308
+ site: {
1309
+ id: '507f1f77bcf86cd799439011',
1310
+ name: 'Main Office',
1311
+ address: {
1312
+ street: '123 Main St',
1313
+ suburb: 'Sydney',
1314
+ state: 'NSW',
1315
+ postcode: '2000',
1316
+ country: 'Australia',
1317
+ formatted: '123 Main St, Sydney NSW 2000',
1318
+ },
596
1319
  },
1320
+ priority: { id: '507f1f77bcf86cd799439011', name: 'High' },
1321
+ type: { id: '507f1f77bcf86cd799439011', name: 'Maintenance' },
1322
+ billingCompany: { id: '507f1f77bcf86cd799439011', name: 'Acme Corp' },
597
1323
  },
598
- priority: { id: '507f1f77bcf86cd799439011', name: 'High' },
599
- type: { id: '507f1f77bcf86cd799439011', name: 'Maintenance' },
600
- billingCompany: { id: '507f1f77bcf86cd799439011', name: 'Acme Corp' },
601
1324
  },
602
1325
  },
603
1326
  type: TriggerStrategy.WEBHOOK,
@@ -617,7 +1340,7 @@ export const job_deleted_trigger = createTrigger({
617
1340
  if (context.propsValue.owner?.length) filters.owner = context.propsValue.owner;
618
1341
  if (context.propsValue.zone?.length) filters.zone = context.propsValue.zone;
619
1342
  if (context.propsValue.status?.length) filters.status = context.propsValue.status.map((v: string) => JSON.parse(v));
620
- // Register webhook with WorkBuddy v2 API (server handles upsert - reactivates if exists)
1343
+ // Register webhook with WorkBuddy v2 API
621
1344
  const response = await httpClient.sendRequest<{ data: { id: string } }>({
622
1345
  method: HttpMethod.POST,
623
1346
  url: `${baseUrl}/api/v2/public/webhooks`,
@@ -649,18 +1372,15 @@ export const job_deleted_trigger = createTrigger({
649
1372
  const webhookId = await context.store.get<string>('webhookId');
650
1373
 
651
1374
  if (webhookId) {
652
- // Pause webhook (server keeps it for potential reactivation)
1375
+ // Delete webhook to avoid stale subscriptions causing duplicate trigger deliveries
653
1376
  await httpClient.sendRequest({
654
- method: HttpMethod.PATCH,
1377
+ method: HttpMethod.DELETE,
655
1378
  url: `${baseUrl}/api/v2/public/webhooks/${webhookId}`,
656
1379
  headers: {
657
1380
  Authorization: `Bearer ${token}`,
658
1381
  'Content-Type': 'application/json',
659
1382
  'X-WorkBuddy-Version': '2026-01',
660
1383
  },
661
- body: {
662
- status: 'paused',
663
- },
664
1384
  });
665
1385
  }
666
1386
  },