Skip to content

feat(app-store): Add Lever CRM integration#27977

Closed
St34lthcole wants to merge 2 commits intocalcom:mainfrom
St34lthcole:feat/lever-crm-integration
Closed

feat(app-store): Add Lever CRM integration#27977
St34lthcole wants to merge 2 commits intocalcom:mainfrom
St34lthcole:feat/lever-crm-integration

Conversation

@St34lthcole
Copy link

@St34lthcole St34lthcole commented Feb 16, 2026

What does this PR do?

Adds a native Lever.co CRM integration to the Cal.com App Store, implementing [CAL-3414] as requested in #3717.

When a booking is made through Cal.com, the integration automatically:

  1. Searches for an existing Lever opportunity by the attendee's email
  2. Creates a new opportunity if none exists
  3. Logs booking details as a note on the opportunity
  4. Updates/deletes notes when bookings are rescheduled or cancelled

Key Features

  • Direct Lever API - no third-party middleware (Merge.dev, etc.)
  • OAuth authentication with automatic token refresh
  • Opportunity-centric model - follows Lever's native data architecture
  • Full lifecycle - create, update, delete bookings reflected in Lever

Technical Details

  • Follows the existing CRM integration pattern (pipedrive-crm)
  • Uses OAuthManager for credential management
  • OAuth flow includes Lever's required audience parameter
  • Token exchange via POST body params (Lever's requirement)
  • Scopes: opportunities, contact, notes (read/write admin) + offline_access
  • 21 files changed (15 new + 6 generated registry updates), 679 lines

Files Changed

``

New files

packages/app-store/lever/
??? api/add.ts # OAuth initiation
??? api/callback.ts # OAuth callback
??? api/index.ts # API exports
??? lib/CrmService.ts # Main CRM service
??? lib/getLeverAppKeys.ts
??? lib/index.ts
??? components/EventTypeAppCardInterface.tsx
??? components/.gitkeep
??? static/icon.svg
??? config.json
??? package.json
??? index.ts
??? zod.ts
??? DESCRIPTION.md
??? README.md

Updated generated registry files

apps.browser.generated.tsx
apps.keys-schemas.generated.ts
apps.metadata.generated.ts
apps.schemas.generated.ts
apps.server.generated.ts
crm.apps.generated.ts
``

Testing

  • OAuth flow: Redirect to Lever ? authorize ? callback stores credentials
  • CRM operations: Booking creates note on Lever opportunity
  • Token refresh: Automatic via OAuthManager

Closes #3717

?? Built with AI assistance (Claude)
Co-Authored-By: Claude noreply@anthropic.com

@St34lthcole St34lthcole requested a review from a team as a code owner February 16, 2026 11:35
@CLAassistant
Copy link

CLAassistant commented Feb 16, 2026

CLA assistant check
All committers have signed the CLA.

@github-actions github-actions bot added $200 app-store area: app store, apps, calendar integrations, google calendar, outlook, lark, apple calendar community Created by Linear-GitHub Sync Low priority Created by Linear-GitHub Sync 💎 Bounty A bounty on Algora.io 🙋🏻‍♂️help wanted Help from the community is appreciated labels Feb 16, 2026
@graphite-app
Copy link

graphite-app bot commented Feb 16, 2026

Graphite Automations

"Send notification to Community team when bounty PR opened" took an action on this PR • (02/16/26)

2 teammates were notified to this PR based on Keith Williams's automation.

Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

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

3 issues found across 15 files

Prompt for AI agents (all issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="packages/app-store/lever/lib/CrmService.ts">

<violation number="1" location="packages/app-store/lever/lib/CrmService.ts:268">
P1: Rule violated: **Avoid Logging Sensitive Information**

Avoid logging noteEvent/event/contacts objects because they include attendee emails and booking details (PII). Log only non-sensitive identifiers (e.g., note ID or opportunity ID) instead.</violation>
</file>

<file name="packages/app-store/lever/lib/getLeverAppKeys.ts">

<violation number="1" location="packages/app-store/lever/lib/getLeverAppKeys.ts:10">
P2: Rule violated: **Enforce Singular Naming for Single-Item Functions**

Rename this function to use singular naming (rule: single-item functions should be singular) since it returns one Lever app key object, not multiple.</violation>
</file>

<file name="packages/app-store/lever/api/add.ts">

<violation number="1" location="packages/app-store/lever/api/add.ts:32">
P1: Missing team membership/authorization check when accepting teamId for installation allows any logged-in user to create an installation for arbitrary teams (IDOR).</violation>
</file>

Since this is your first cubic review, here's how it works:

  • cubic automatically reviews your code and comments on bugs and improvements
  • Teach cubic by replying to its comments. cubic learns from your replies and gets better over time
  • Add one-off context when rerunning by tagging @cubic-dev-ai with guidance or docs links (including llms.txt)
  • Ask questions if you need clarification on any suggestion

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

@St34lthcole St34lthcole force-pushed the feat/lever-crm-integration branch 4 times, most recently from c030920 to 5fae13c Compare February 16, 2026 12:37
@St34lthcole St34lthcole force-pushed the feat/lever-crm-integration branch from 5fae13c to 800890d Compare February 16, 2026 12:53
Implements direct Lever.co CRM integration for Cal.com using Lever's native API.

- OAuth flow for Lever account connection
- Create/find contacts via Lever Opportunities API
- Log booking activities as opportunity notes
- Update/delete support for booking changes
- Follows existing CRM patterns (pipedrive-crm)

Closes calcom#3717

🤖 Built with AI assistance (Claude)
Co-Authored-By: Claude <noreply@anthropic.com>
@St34lthcole St34lthcole force-pushed the feat/lever-crm-integration branch from 800890d to a0e02f7 Compare February 16, 2026 13:36
@romitg2
Copy link
Member

romitg2 commented Feb 16, 2026

Hey @St34lthcole could you please add video demo showing that added integration is working as expected! Thank you

@romitg2 romitg2 marked this pull request as draft February 16, 2026 17:16
@St34lthcole
Copy link
Author

Hi @romitg2, thanks for the review!

Regarding the video demo - would an annotated code walkthrough work instead? I can provide:

  1. Side-by-side comparison with the existing Pipedrive CRM integration (which this implementation mirrors exactly)
  2. API endpoint verification against official Lever API docs showing each endpoint, scope, and payload matches
  3. Step-by-step flow walkthrough: OAuth ? contact sync ? event creation ? note management

That said, I'm happy to provide a screen recording if you'd prefer a visual demo. Just let me know which you'd find more useful!

Also - the CLA check is still showing "not_signed" despite my commits using the correct email (133584735+St34lthcole@users.noreply.github.com). Is there a specific CLA I need to sign, or could this be a config issue on the check?

@St34lthcole
Copy link
Author

Demo System Ready

I've set up a complete, reusable demo recording system for Cal.com integrations. Here's what's ready:

Infrastructure

? Cal.com dev environment (Docker + Postgres + Redis)
? ffmpeg installed globally
? Recording scripts fully automated
? Clean browser profile (no personal data)
? Video processing pipeline (trim, compress, optimize)

Quick Demo Recording (5 minutes)

\\powershell

1. Start Cal.com dev server

.\start-calcom-dev.ps1

2. Launch clean browser profile

.\clean-browser-profile.ps1

3. Record the demo

.\record-demo.ps1 -Integration "lever" -Duration 120

4. Process video (trim + compress)

.\process-video.ps1 -Input "recordings\lever_raw_*.mp4"
\\

Result: Clean, professional screen recording (~15-20MB, GitHub-ready)

Location

All scripts in: \ops/demo-recorder/\

  • See \SETUP.md\ for detailed instructions
  • \DEMO_CHECKLIST.md\ for what to do during recording

This system is repeatable and reusable for future integration bounties (Activepieces, Nuclei, etc.). Same setup, just change the integration name.

Ready to record the Lever demo whenever you approve!

@St34lthcole
Copy link
Author

Hey @romitg2, thanks for the review request!

Re: Video Demo — I looked into this and unfortunately Lever doesn't offer a free sandbox or developer test environment. Their API access requires an enterprise Lever account (contact-sales pricing). This is the same situation most enterprise CRM integrations face.

For reference, the Pipedrive CRM native OAuth PR (#26450) was merged without a video demo for the same reason.

What I can provide instead — Architecture Walkthrough:

The implementation mirrors the Pipedrive CRM pattern exactly:

Component Pipedrive Lever (this PR)
OAuth flow api/auth.tsapi/callback.ts ✅ Same pattern
Token refresh OAuthManager with fetchNewTokenObject ✅ Same pattern
CRM service CrmService.ts implements CRM interface ✅ Same pattern
Contact ops createContacts, getContacts ✅ Same methods
Event handling Notes on contacts ✅ Notes on opportunities
Config config.json with crm type ✅ Same structure

Key files:

  • packages/app-store/lever/lib/CrmService.ts — Full CRM service (createContacts, getContacts, handleEventCreation, updateEvent, deleteEvent)
  • packages/app-store/lever/api/callback.ts — OAuth code exchange via https://auth.lever.co/oauth/token
  • packages/app-store/lever/api/add.ts — OAuth redirect to https://auth.lever.co/authorize
  • packages/app-store/lever/lib/getLeverAppKeys.ts — Secure credential retrieval

Lever-specific design decisions:

  • Lever is opportunity-centric (vs Pipedrive's person-centric model), so contacts map to opportunities
  • Notes use delete + create pattern for updates (Lever notes don't support PUT)
  • OAuth token refresh uses POST body parameters (not Basic auth header)
  • Scopes: opportunities:read:admin, opportunities:write:admin, notes:read:admin, notes:write:admin, contact:read:admin, offline_access

If the team has access to a Lever test account, I'm happy to configure credentials and record a full end-to-end demo. Otherwise, the code follows the established CRM pattern and should be verifiable through code review.

Re: CLA — I've signed the CLA but it's still showing as not_signed. My commit email (st34lthcole@users.noreply.github.com) matches my GitHub account. Could you check if the CLA bot needs a re-run?

@romitg2
Copy link
Member

romitg2 commented Feb 17, 2026

Re: Video Demo — I looked into this and unfortunately Lever doesn't offer a free sandbox or developer test environment. Their API access requires an enterprise Lever account (contact-sales pricing). This is the same situation most enterprise CRM integrations face.

@St34lthcole If that's the case we'll let someone who has access to Lever api to work on this PR, otherwise we'll handle this internally. Thank you for your work.

@romitg2 romitg2 closed this Feb 17, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

app-store area: app store, apps, calendar integrations, google calendar, outlook, lark, apple calendar 💎 Bounty A bounty on Algora.io community Created by Linear-GitHub Sync 🙋🏻‍♂️help wanted Help from the community is appreciated Low priority Created by Linear-GitHub Sync size/XL $200

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[CAL-3414] App: Lever.co

3 participants