Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
2e89fe5
fix(triggers): apply webhook audit follow-ups
waleedlatif1 Apr 6, 2026
bb716bb
fix(webhooks): Salesforce provider handler, Zoom CRC and block wiring
waleedlatif1 Apr 6, 2026
0ddc769
fix(webhooks): harden Resend and Linear triggers (idempotency, auth, …
waleedlatif1 Apr 6, 2026
e9618d9
fix(webhooks): harden Vercel and Greenhouse trigger handlers
waleedlatif1 Apr 6, 2026
317d4ab
fix(gong): JWT verification, trigger UX, alignment script
waleedlatif1 Apr 6, 2026
729667a
fix(notion): align webhook lifecycle and outputs
waleedlatif1 Apr 6, 2026
e79c556
fix(webhooks): tighten remaining provider hardening
waleedlatif1 Apr 7, 2026
23ccc9b
refactor(webhooks): move subscription helpers out of providers
waleedlatif1 Apr 7, 2026
e000c5b
fix(zoom): resolve env-backed secrets during validation
waleedlatif1 Apr 7, 2026
b50a902
fix build
waleedlatif1 Apr 7, 2026
732755a
consolidate tests
waleedlatif1 Apr 7, 2026
7c31044
refactor(salesforce): share payload object type parsing
waleedlatif1 Apr 7, 2026
41b0348
fix(webhooks): address remaining review follow-ups
waleedlatif1 Apr 7, 2026
cae9c8b
test(webhooks): separate Zoom coverage and clean Notion output shape
waleedlatif1 Apr 7, 2026
a305fc2
feat(triggers): enrich Vercel and Greenhouse webhook output shapes
waleedlatif1 Apr 7, 2026
3e29341
feat(webhooks): enrich Resend trigger outputs; clarify Notion output …
waleedlatif1 Apr 7, 2026
5148936
feat(webhooks): enrich Zoom and Gong trigger output schemas
waleedlatif1 Apr 7, 2026
0600c90
feat(triggers): enrich Salesforce and Linear webhook output schemas
waleedlatif1 Apr 7, 2026
1cd27d8
remove from mdx
waleedlatif1 Apr 7, 2026
e0580f7
chore(webhooks): expand trigger alignment coverage
waleedlatif1 Apr 7, 2026
3e7a046
updated skills
waleedlatif1 Apr 7, 2026
d3fcf04
updated file naming semantics
waleedlatif1 Apr 7, 2026
2897ce1
rename file
waleedlatif1 Apr 7, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
feat(webhooks): enrich Resend trigger outputs; clarify Notion output …
…docs

- Resend: expose broadcast_id, template_id, tags, and data_created_at from
  payload data (per Resend webhook docs); keep alignment with formatInput.
- Add resend entry to check-trigger-alignment and unit test for formatInput.
- Notion: tighten output descriptions for authors, entity types, parent types,
  attempt_number, and accessible_by per Notion webhooks event reference.

Made-with: Cursor
  • Loading branch information
waleedlatif1 committed Apr 7, 2026
commit 3e293410f802934fc7a5ed271bbf7de99be9333b
45 changes: 45 additions & 0 deletions apps/sim/lib/webhooks/providers/resend.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { describe, expect, it } from 'vitest'
import { resendHandler } from '@/lib/webhooks/providers/resend'

describe('Resend webhook provider', () => {
it('formatInput exposes documented email metadata and distinct data.created_at', async () => {
const { input } = await resendHandler.formatInput!({
webhook: {},
workflow: { id: 'wf', userId: 'u' },
body: {
type: 'email.bounced',
created_at: '2024-11-22T23:41:12.126Z',
data: {
broadcast_id: '8b146471-e88e-4322-86af-016cd36fd216',
created_at: '2024-11-22T23:41:11.894719+00:00',
email_id: '56761188-7520-42d8-8898-ff6fc54ce618',
from: 'Acme <onboarding@resend.dev>',
to: ['delivered@resend.dev'],
subject: 'Sending this example',
template_id: '43f68331-0622-4e15-8202-246a0388854b',
tags: { category: 'confirm_email' },
bounce: {
message: 'Hard bounce',
subType: 'Suppressed',
type: 'Permanent',
},
},
},
headers: {},
requestId: 'test',
})

expect(input).toMatchObject({
type: 'email.bounced',
created_at: '2024-11-22T23:41:12.126Z',
data_created_at: '2024-11-22T23:41:11.894719+00:00',
email_id: '56761188-7520-42d8-8898-ff6fc54ce618',
broadcast_id: '8b146471-e88e-4322-86af-016cd36fd216',
template_id: '43f68331-0622-4e15-8202-246a0388854b',
tags: { category: 'confirm_email' },
bounceType: 'Permanent',
bounceSubType: 'Suppressed',
bounceMessage: 'Hard bounce',
})
})
})
11 changes: 11 additions & 0 deletions apps/sim/lib/webhooks/providers/resend.ts
Original file line number Diff line number Diff line change
Expand Up @@ -121,13 +121,24 @@ export const resendHandler: WebhookProviderHandler = {
const data = payload.data as Record<string, unknown> | undefined
const bounce = data?.bounce as Record<string, unknown> | undefined
const click = data?.click as Record<string, unknown> | undefined
const dataCreatedAt = data?.created_at
const dataCreatedAtStr =
typeof dataCreatedAt === 'string'
? dataCreatedAt
: dataCreatedAt != null
? String(dataCreatedAt)
: null

return {
input: {
type: payload.type,
created_at: payload.created_at,
data_created_at: dataCreatedAtStr,
data: data ?? null,
email_id: data?.email_id ?? null,
broadcast_id: data?.broadcast_id ?? null,
template_id: data?.template_id ?? null,
tags: data?.tags ?? null,
from: data?.from ?? null,
to: data?.to ?? null,
subject: data?.subject ?? null,
Expand Down
37 changes: 37 additions & 0 deletions apps/sim/scripts/check-trigger-alignment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,43 @@ const PROVIDER_CHECKS: Record<string, CheckFn> = {
formatInputKeys: Object.keys(input).sort(),
}
},
resend: async () => {
const { buildResendOutputs } = await import('@/triggers/resend/utils')
const { resendHandler } = await import('@/lib/webhooks/providers/resend')
const outputs = buildResendOutputs() as Record<string, TriggerOutput>
const result = await resendHandler.formatInput!({
webhook: {},
workflow: { id: 'check-alignment', userId: 'check-alignment' },
body: {
type: 'email.bounced',
created_at: '2024-11-22T23:41:12.126Z',
data: {
broadcast_id: '8b146471-e88e-4322-86af-016cd36fd216',
created_at: '2024-11-22T23:41:11.894719+00:00',
email_id: '56761188-7520-42d8-8898-ff6fc54ce618',
from: 'Acme <onboarding@resend.dev>',
to: ['delivered@resend.dev'],
subject: 'Sending this example',
template_id: '43f68331-0622-4e15-8202-246a0388854b',
bounce: {
message:
"The recipient's email address is on the suppression list because it has a recent history of producing hard bounces.",
subType: 'Suppressed',
type: 'Permanent',
},
tags: { category: 'confirm_email' },
},
},
headers: {},
requestId: 'check-trigger-alignment',
})
const input = result.input as Record<string, unknown>
return {
referenceLabel: 'buildResendOutputs()',
outputKeys: Object.keys(outputs).sort(),
formatInputKeys: Object.keys(input).sort(),
}
},
notion: async () => {
const { buildPageEventOutputs } = await import('@/triggers/notion/utils')
const { notionHandler } = await import('@/lib/webhooks/providers/notion')
Expand Down
47 changes: 34 additions & 13 deletions apps/sim/triggers/notion/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,10 +84,14 @@ function buildBaseOutputs(): Record<string, TriggerOutput> {
workspace_name: { type: 'string', description: 'Workspace name' },
subscription_id: { type: 'string', description: 'Webhook subscription ID' },
integration_id: { type: 'string', description: 'Integration ID that received the event' },
attempt_number: { type: 'number', description: 'Delivery attempt number' },
attempt_number: {
type: 'number',
description: 'Delivery attempt number (1-8 per Notion retries)',
},
accessible_by: {
type: 'array',
description: 'Array of users and bots that can access the entity',
description:
'Users and bots with access to the entity (`id` + `type` per object); `type` is `person` or `bot`. Omitted on some deliveries (treat as empty).',
},
}
}
Expand All @@ -97,8 +101,14 @@ function buildBaseOutputs(): Record<string, TriggerOutput> {
*/
function buildEntityOutputs(): Record<string, TriggerOutput> {
return {
id: { type: 'string', description: 'Entity ID (page or database ID)' },
entity_type: { type: 'string', description: 'Entity type (page, database, block, or comment)' },
id: {
type: 'string',
description: 'Entity ID (page, database, block, comment, or data source ID)',
},
entity_type: {
type: 'string',
description: 'Entity type: `page`, `database`, `block`, `comment`, or `data_source`',
},
}
}

Expand All @@ -110,7 +120,8 @@ export function buildPageEventOutputs(): Record<string, TriggerOutput> {
...buildBaseOutputs(),
authors: {
type: 'array',
description: 'Array of users who triggered the event',
description:
'Actors who triggered the event (`id` + `type` per object); `type` is `person`, `bot`, or `agent` per Notion',
},
entity: buildEntityOutputs(),
data: {
Expand All @@ -123,10 +134,13 @@ export function buildPageEventOutputs(): Record<string, TriggerOutput> {
description: 'Property IDs updated as part of the event, when provided by Notion',
},
parent: {
id: { type: 'string', description: 'Parent page or database ID' },
id: {
type: 'string',
description: 'Parent page, database, workspace (space), or block ID',
},
parent_type: {
type: 'string',
description: 'Parent type (database, page, block, or workspace)',
description: 'Parent type: `page`, `database`, `block`, `workspace`, or `space`',
},
},
},
Expand All @@ -141,7 +155,8 @@ export function buildDatabaseEventOutputs(): Record<string, TriggerOutput> {
...buildBaseOutputs(),
authors: {
type: 'array',
description: 'Array of users who triggered the event',
description:
'Actors who triggered the event (`id` + `type` per object); `type` is `person`, `bot`, or `agent` per Notion',
},
entity: buildEntityOutputs(),
data: {
Expand All @@ -154,8 +169,11 @@ export function buildDatabaseEventOutputs(): Record<string, TriggerOutput> {
description: 'Database properties updated as part of the event, when provided by Notion',
},
parent: {
id: { type: 'string', description: 'Parent page or workspace ID' },
parent_type: { type: 'string', description: 'Parent type (page, database, or workspace)' },
id: { type: 'string', description: 'Parent page, database, workspace, or space ID' },
parent_type: {
type: 'string',
description: 'Parent type: `page`, `database`, `workspace`, or `space`',
},
},
},
}
Expand All @@ -169,7 +187,8 @@ export function buildCommentEventOutputs(): Record<string, TriggerOutput> {
...buildBaseOutputs(),
authors: {
type: 'array',
description: 'Array of users who triggered the event',
description:
'Actors who triggered the event (`id` + `type` per object); `type` is `person`, `bot`, or `agent` per Notion',
},
entity: {
id: { type: 'string', description: 'Comment ID' },
Expand All @@ -193,15 +212,17 @@ export function buildGenericWebhookOutputs(): Record<string, TriggerOutput> {
...buildBaseOutputs(),
authors: {
type: 'array',
description: 'Array of users who triggered the event',
description:
'Actors who triggered the event (`id` + `type` per object); `type` is `person`, `bot`, or `agent` per Notion',
},
entity: buildEntityOutputs(),
data: {
parent: {
id: { type: 'string', description: 'Parent entity ID, when provided by Notion' },
parent_type: {
type: 'string',
description: 'Parent entity type (page, database, block, or workspace), when present',
description:
'Parent type (`page`, `database`, `block`, `workspace`, `space`, …), when present',
},
},
page_id: { type: 'string', description: 'Page ID related to the event, when present' },
Expand Down
20 changes: 19 additions & 1 deletion apps/sim/triggers/resend/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ export function buildResendExtraFields(triggerId: string) {

/**
* Common fields present in all Resend email webhook payloads
* (see https://resend.com/docs/dashboard/webhooks/introduction — example `data` object).
*/
const commonEmailOutputs = {
type: {
Expand All @@ -103,12 +104,29 @@ const commonEmailOutputs = {
},
created_at: {
type: 'string',
description: 'Event creation timestamp (ISO 8601)',
description: 'Webhook event creation timestamp (ISO 8601), top-level `created_at`',
},
data_created_at: {
type: 'string',
description:
'Email record timestamp from payload `data.created_at` (ISO 8601), when present — distinct from top-level `created_at`',
},
email_id: {
type: 'string',
description: 'Unique email identifier',
},
broadcast_id: {
type: 'string',
description: 'Broadcast ID associated with the email, when sent as part of a broadcast',
},
template_id: {
type: 'string',
description: 'Template ID used to send the email, when applicable',
},
tags: {
type: 'json',
description: 'Tag key/value metadata attached to the email (payload `data.tags`)',
},
from: {
type: 'string',
description: 'Sender email address',
Expand Down