Skip to content
Merged
Prev Previous commit
Next Next commit
idempotency
  • Loading branch information
waleedlatif1 committed Apr 7, 2026
commit ca3c7d0248da16fe0d4224437db06b494f903da7
4 changes: 3 additions & 1 deletion apps/sim/lib/core/idempotency/service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -422,7 +422,9 @@ export class IdempotencyService {
normalizedHeaders?.['x-teams-notification-id'] ||
normalizedHeaders?.['svix-id'] ||
normalizedHeaders?.['linear-delivery'] ||
normalizedHeaders?.['greenhouse-event-id']
normalizedHeaders?.['greenhouse-event-id'] ||
normalizedHeaders?.['x-zm-request-id'] ||
normalizedHeaders?.['idempotency-key']

if (webhookIdHeader) {
return `${webhookId}:${webhookIdHeader}`
Expand Down
9 changes: 9 additions & 0 deletions apps/sim/lib/webhooks/providers/ashby.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,15 @@ function validateAshbySignature(secretToken: string, signature: string, body: st
}

export const ashbyHandler: WebhookProviderHandler = {
extractIdempotencyId(body: unknown): string | null {
const obj = body as Record<string, unknown>
const webhookActionId = obj.webhookActionId
if (typeof webhookActionId === 'string' && webhookActionId) {
return `ashby:${webhookActionId}`
}
return null
},

async formatInput({ body }: FormatInputContext): Promise<FormatInputResult> {
const b = body as Record<string, unknown>
return {
Expand Down
14 changes: 14 additions & 0 deletions apps/sim/lib/webhooks/providers/gong.ts
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,20 @@ export async function verifyGongJwtAuth(ctx: AuthContext): Promise<NextResponse
export const gongHandler: WebhookProviderHandler = {
verifyAuth: verifyGongJwtAuth,

extractIdempotencyId(body: unknown): string | null {
const obj = body as Record<string, unknown>
const callData = obj.callData as Record<string, unknown> | undefined
const metaData = callData?.metaData as Record<string, unknown> | undefined
const id = metaData?.id
if (typeof id === 'string' && id) {
return `gong:${id}`
}
if (typeof id === 'number') {
return `gong:${id}`
}
return null
},

async formatInput({ body }: FormatInputContext): Promise<FormatInputResult> {
const b = body as Record<string, unknown>
const callData = b.callData as Record<string, unknown> | undefined
Expand Down
9 changes: 9 additions & 0 deletions apps/sim/lib/webhooks/providers/telegram.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,15 @@ export const telegramHandler: WebhookProviderHandler = {
return null
},

extractIdempotencyId(body: unknown): string | null {
const obj = body as Record<string, unknown>
const updateId = obj.update_id
if (typeof updateId === 'number') {
return `telegram:${updateId}`
}
return null
},

async formatInput({ body }: FormatInputContext): Promise<FormatInputResult> {
const b = body as Record<string, unknown>
const rawMessage = (b?.message ||
Expand Down
30 changes: 0 additions & 30 deletions apps/sim/lib/webhooks/providers/zoom.ts
Original file line number Diff line number Diff line change
Expand Up @@ -128,36 +128,6 @@ export const zoomHandler: WebhookProviderHandler = {
return null
},

extractIdempotencyId(body: unknown): string | null {
Comment thread
waleedlatif1 marked this conversation as resolved.
const obj = body as Record<string, unknown>
const event = obj.event
const ts = obj.event_ts
if (typeof event !== 'string' || ts === undefined || ts === null) {
return null
}
const payload = obj.payload as Record<string, unknown> | undefined
const inner = payload?.object as Record<string, unknown> | undefined
const participant =
inner?.participant &&
typeof inner.participant === 'object' &&
!Array.isArray(inner.participant)
? (inner.participant as Record<string, unknown>)
: null
const participantStable =
(typeof participant?.user_id === 'string' && participant.user_id) ||
(typeof participant?.id === 'string' && participant.id) ||
(typeof participant?.email === 'string' && participant.email) ||
(typeof participant?.join_time === 'string' && participant.join_time) ||
(typeof participant?.leave_time === 'string' && participant.leave_time) ||
''
const stable =
participantStable ||
(typeof inner?.uuid === 'string' && inner.uuid) ||
(inner?.id !== undefined && inner.id !== null ? String(inner.id) : '') ||
''
return `zoom:${event}:${String(ts)}:${stable}`
},

async matchEvent({ webhook: wh, workflow, body, requestId, providerConfig }: EventMatchContext) {
const triggerId = providerConfig.triggerId as string | undefined
const obj = body as Record<string, unknown>
Expand Down
Loading