Audit an existing Sim webhook trigger against the service's webhook API docs and repository conventions, then report and fix issues across trigger definitions, provider handler, output alignment, registration, and security. Use when validating or repairing a trigger under `apps/sim/triggers/{service}/` or `apps/sim/lib/webhooks/providers/{service}.ts`.
You are an expert auditor for Sim webhook triggers. Your job is to validate that an existing trigger implementation is correct, complete, secure, and aligned across all layers.
Read every file for the trigger — do not skip any:
apps/sim/triggers/{service}/ # All trigger files, utils.ts, index.ts
apps/sim/lib/webhooks/providers/{service}.ts # Provider handler (if exists)
apps/sim/lib/webhooks/providers/registry.ts # Handler registry
apps/sim/triggers/registry.ts # Trigger registry
apps/sim/blocks/blocks/{service}.ts # Block definition (trigger wiring)
Also read for reference:
apps/sim/lib/webhooks/providers/types.ts # WebhookProviderHandler interface
apps/sim/lib/webhooks/providers/utils.ts # Shared helpers (createHmacVerifier, etc.)
apps/sim/lib/webhooks/provider-subscription-utils.ts # Subscription helpers
apps/sim/lib/webhooks/processor.ts # Central webhook processor
Fetch the service's official webhook documentation. This is the source of truth for:
If the official docs do not clearly show the webhook payload JSON for an event, you MUST tell the user instead of guessing.
formatInput mappings that are not backed by docs or live payloadsIf a payload schema is unknown, validation must explicitly recommend:
{service}TriggerOptions lists all trigger IDs accurately{service}SetupInstructions provides clear, correct steps for the servicebuild{Service}ExtraFields includes relevant filter/config fields with correct conditionoptional: true or items (tool-output-only features)includeDropdown: trueincludeDropdownbuildTriggerSubBlocks helper (not hand-rolled subBlocks)id matches the convention {service}_{event_name}provider matches the service name used in the handler registryindex.ts barrel exports all triggersmatchEvent logic exists in {service}TriggerOptionsis{Service}EventMatch (if exists) correctly identifies events per the API docsverifyAuth correctly validates webhook signatures per the service's documentationsha256= prefix, base64, etc.)safeCompare for timing-safe comparison (no ===)webhookSecret is required, handler rejects when it's missing (fail-closed)matchEvent returns boolean (not NextResponse or other values)endpoint.url_validation)triggerId is a generic webhook ID, all events pass throughtriggerId is specific, only matching events passawait import() for trigger utils (avoids circular deps)formatInput return matches a key in the trigger outputs schemaoutputs schema is populated by formatInputwebhook: { ... }, {service}: { ... })resource.id actually has resource: { id: ... })null is used for missing optional fields (not empty strings or empty objects){ input: { ... } } — not a bare objectextractIdempotencyId returns a stable, unique key per deliveryX-Request-Id, Linear-Delivery, svix-id)${type}:${id}) when no delivery header existshandleChallenge correctly implements the service's URL verification handshakeresolveEnvVarsInObject if neededIf the service supports programmatic webhook creation:
getNotificationUrl(ctx.webhook){ providerConfigUpdates: { externalId } } with the external webhook IDapiKey or externalId is missingroute.ts, provider-subscriptions.ts, or deploy.tscreateSubscription/deleteSubscription)triggers/registry.ts)providers/registry.ts)provider field on the trigger configsblocks/blocks/{service}.ts)triggers.enabled: truetriggers.available lists all trigger IDssubBlocks: ...getTrigger('id').subBlockstriggers.available that aren't in the registrytriggers.available=== (must use safeCompare or crypto.timingSafeEqual)Group findings by severity:
Critical (runtime errors, security issues, or data loss):
formatInput keys don't match trigger outputsverifyAuth when the service sends signed webhooksmatchEvent returns non-boolean valuescreateSubscription calling wrong API endpoint=== instead of safeCompareWarning (convention violations or usability issues):
extractIdempotencyId when the service provides delivery IDsformatInput returns (undiscoverable data)matchEvent not filtering challenge/verification eventsSuggestion (minor improvements):
createSubscriptionAfter reporting, fix every critical and warning issue. Apply suggestions where they don't add unnecessary complexity.
After fixing, confirm:
bun run type-check passesbun test {service}includeDropdown)outputs key ↔ every formatInput keybun run type-check passes after fixes