Skip to content

feat(triggers): add Greenhouse webhook triggers#3985

Merged
waleedlatif1 merged 3 commits intostagingfrom
waleedlatif1/add-greenhouse-trigger
Apr 6, 2026
Merged

feat(triggers): add Greenhouse webhook triggers#3985
waleedlatif1 merged 3 commits intostagingfrom
waleedlatif1/add-greenhouse-trigger

Conversation

@waleedlatif1
Copy link
Copy Markdown
Collaborator

Summary

  • Add 8 webhook triggers for Greenhouse ATS: Candidate Hired, New Application, Candidate Stage Change, Candidate Rejected, Offer Created, Job Created, Job Updated, and generic webhook
  • Output schemas match actual Greenhouse webhook payload structures (candidate nested inside application, jobs array, flat offer payload)
  • Event filtering via provider handler registry prevents mismatched events from firing wrong triggers
  • Manual webhook setup with instructions pointing to Greenhouse Dev Center

Type of Change

  • New feature

Testing

Tested manually

Checklist

  • Code follows project style guidelines
  • Self-reviewed my changes
  • Tests added/updated and passing
  • No new warnings introduced
  • I confirm that I have read and agree to the terms outlined in the Contributor License Agreement (CLA)

Add 8 webhook triggers for Greenhouse ATS events:
- Candidate Hired, New Application, Stage Change, Rejected
- Offer Created, Job Created, Job Updated
- Generic Webhook (all events)

Includes event filtering via provider handler registry and output
schemas matching actual Greenhouse webhook payload structures.
@vercel
Copy link
Copy Markdown

vercel bot commented Apr 6, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
docs Skipped Skipped Apr 6, 2026 6:29pm

Request Review

@cursor
Copy link
Copy Markdown

cursor bot commented Apr 6, 2026

PR Summary

Medium Risk
Adds a new webhook provider with HMAC signature verification and event-type filtering, which impacts webhook authentication and trigger dispatch paths. Risk is moderate due to new integration surface area and reliance on correct action mapping/signature header handling.

Overview
Adds Greenhouse webhook trigger support by introducing 8 new triggers (candidate/application/job/offer events plus a generic all-events webhook) with defined output schemas and setup/secret-key subblocks.

Registers a new greenhouse webhook provider handler that verifies optional HMAC-SHA256 signatures (via Signature: sha256 <hex>) and filters executions by matching the incoming action to the configured trigger (except the generic trigger). Greenhouse is also updated to advertise trigger availability and include the trigger configuration subblocks in the Greenhouse block UI.

Reviewed by Cursor Bugbot for commit 8518fe3. Configure here.

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps bot commented Apr 6, 2026

Greptile Summary

This PR adds 8 Greenhouse ATS webhook triggers (Candidate Hired, New Application, Candidate Stage Change, Candidate Rejected, Offer Created, Job Created, Job Updated, and a generic catch-all). The implementation is well-structured and follows the established codebase patterns: shared output-schema builders live in a central utils.ts, event filtering is handled via a GREENHOUSE_EVENT_MAP in the provider handler, and HMAC-SHA256 signature verification is wired through the createHmacVerifier factory. Previous review concerns (static import, HMAC verification, and buildJobPayload extraction) have all been addressed.

  • All 8 triggers are correctly registered in triggers/registry.ts and the greenhouse provider handler is wired in lib/webhooks/providers/registry.ts.
  • The GREENHOUSE_EVENT_MAP and isGreenhouseEventMatch correctly map trigger IDs to Greenhouse action strings, and the matchEvent handler properly returns HTTP 200 (acknowledge-but-skip) for non-matching events.
  • Output schemas match the actual Greenhouse webhook payload structures, with the candidate-inside-application nesting for candidate events and a flat layout for offer events.
  • The secretKey field in buildGreenhouseExtraFields correctly uses a shared ID so its value persists across trigger-type switches within the block.
  • One minor style issue: the secretKey subblock is missing paramVisibility: 'user-only', which is the correct annotation for manually-entered user credentials (as opposed to framework-injected OAuth tokens)."

Confidence Score: 5/5

Safe to merge — the single remaining finding is a minor style/best-practice omission that does not affect runtime correctness.

All P0/P1 concerns raised in prior review rounds (static import, HMAC verification, duplicated job payload) have been resolved. The only outstanding issue is a missing paramVisibility: 'user-only' on the secretKey subblock — a P2 style concern that does not break functionality.

apps/sim/triggers/greenhouse/utils.ts — buildGreenhouseExtraFields should add paramVisibility: 'user-only' to the secretKey subblock.

Important Files Changed

Filename Overview
apps/sim/triggers/greenhouse/utils.ts Central utility file with output-schema builders, event map, and extra-field builder — all correct; secretKey subblock is missing paramVisibility: 'user-only'
apps/sim/lib/webhooks/providers/greenhouse.ts Provider handler with HMAC-SHA256 verification via createHmacVerifier and event-matching via static isGreenhouseEventMatch import — implementation is correct
apps/sim/triggers/greenhouse/candidate_hired.ts Primary trigger (includes dropdown) for hire_candidate events — structure and config are correct
apps/sim/triggers/greenhouse/webhook.ts Generic catch-all trigger accepting all Greenhouse events — correctly omits event filtering
apps/sim/blocks/blocks/greenhouse.ts Block config with trigger capability enabled and all 8 trigger subBlocks spread in correctly
apps/sim/triggers/registry.ts All 8 Greenhouse triggers registered alphabetically in the correct registry position
apps/sim/lib/webhooks/providers/registry.ts greenhouseHandler registered under the greenhouse provider key — correct

Sequence Diagram

sequenceDiagram
    participant GH as Greenhouse
    participant WH as Webhook Endpoint
    participant PH as Provider Handler (greenhouse)
    participant EM as Event Matcher
    participant WE as Workflow Executor

    GH->>WH: POST /webhook/{id}<br/>Signature: sha256 <digest>
    WH->>PH: verifyAuth(request, rawBody, providerConfig)
    alt secretKey configured
        PH->>PH: validateGreenhouseSignature(secret, signature, body)
        alt Signature invalid
            PH-->>WH: 401 Unauthorized
            WH-->>GH: 401
        end
    end
    PH->>PH: formatInput() → { action, payload }
    PH->>EM: matchEvent(triggerId, action)
    alt triggerId !== greenhouse_webhook
        EM->>EM: isGreenhouseEventMatch(triggerId, action)
        alt Action mismatch
            EM-->>WH: 200 { message: "Ignoring" }
            WH-->>GH: 200
        end
    end
    EM-->>WH: true (proceed)
    WH->>WE: Execute workflow with { action, payload }
    WE-->>WH: Execution result
    WH-->>GH: 200 OK
Loading

Reviews (3): Last reviewed commit: "fix(triggers): align rejection_reason ou..." | Re-trigger Greptile

- Fix rejection_reason.type key collision with mock payload generator
  by renaming to reason_type
- Replace dynamic import with static import in matchEvent handler
- Add HMAC-SHA256 signature verification via createHmacVerifier
- Add secretKey extra field to all trigger subBlocks
- Extract shared buildJobPayload helper to deduplicate job outputs
@waleedlatif1
Copy link
Copy Markdown
Collaborator Author

@greptile

@waleedlatif1
Copy link
Copy Markdown
Collaborator Author

@cursor review

…ayload

Reverted reason_type rename — instead flattened rejection_reason to JSON
type since TriggerOutput's type?: string conflicts with nested type keys.
Also hardened processOutputField to check typeof type === 'string' before
treating an object as a leaf node, preventing this class of bug for future triggers.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@waleedlatif1
Copy link
Copy Markdown
Collaborator Author

@greptile

@waleedlatif1
Copy link
Copy Markdown
Collaborator Author

@cursor review

Copy link
Copy Markdown

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit 8518fe3. Configure here.

@waleedlatif1 waleedlatif1 merged commit 7ea0693 into staging Apr 6, 2026
12 checks passed
@waleedlatif1 waleedlatif1 deleted the waleedlatif1/add-greenhouse-trigger branch April 6, 2026 18:59
emir-karabeg pushed a commit that referenced this pull request Apr 7, 2026
* feat(triggers): add Greenhouse webhook triggers

Add 8 webhook triggers for Greenhouse ATS events:
- Candidate Hired, New Application, Stage Change, Rejected
- Offer Created, Job Created, Job Updated
- Generic Webhook (all events)

Includes event filtering via provider handler registry and output
schemas matching actual Greenhouse webhook payload structures.

* fix(triggers): address PR review feedback for Greenhouse triggers

- Fix rejection_reason.type key collision with mock payload generator
  by renaming to reason_type
- Replace dynamic import with static import in matchEvent handler
- Add HMAC-SHA256 signature verification via createHmacVerifier
- Add secretKey extra field to all trigger subBlocks
- Extract shared buildJobPayload helper to deduplicate job outputs

* fix(triggers): align rejection_reason output with actual Greenhouse payload

Reverted reason_type rename — instead flattened rejection_reason to JSON
type since TriggerOutput's type?: string conflicts with nested type keys.
Also hardened processOutputField to check typeof type === 'string' before
treating an object as a leaf node, preventing this class of bug for future triggers.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant