Polar Licensing Integration
Relevant source files
The following files were used as context for generating this wiki page:
- apps/desktop/Sources/CrispCore/Licensing/PolarConfig.swift
- apps/desktop/Sources/CrispCore/Licensing/PolarService.swift
- apps/desktop/Sources/Crisp/Services/Licensing/LicenseStore.swift
- services/polar-license-lookup/api/license.js
- services/polar-license-lookup/README.md
- apps/desktop/build.sh
- CLAUDE.md
Crisp integrates with Polar.sh to manage a paid tier ("Crisp Pro") for its macOS application. This integration provides automated license key lookup, device-bound activation, and periodic re-validation to enforce subscription status. The system is designed to be "dark" (disabled) by default, enabled only through specific build-time flags and environment variables.
The architecture consists of a native Swift client in the desktop app, a serverless Vercel function for secure license lookups, and the Polar.sh API for license management. This allows the app to complete purchases silently via deep links while keeping sensitive API tokens out of the distributed client.
Sources: apps/desktop/Sources/CrispCore/Licensing/PolarConfig.swift:5-15, services/polar-license-lookup/README.md:1-8
System Architecture
The integration spans three distinct environments: the macOS desktop application, a secure serverless proxy, and the Polar.sh backend.
Component Relationship
The desktop app communicates directly with Polar for public validation and activation but uses a serverless proxy for operations requiring high-privilege API tokens.
The diagram shows the auto-activation flow where the application resolves a license key from a checkout ID without exposing the POLAR_TOKEN.
Sources: services/polar-license-lookup/api/license.js:28-60, services/polar-license-lookup/README.md:1-12
Secure License Lookup (Serverless)
A Vercel-hosted serverless function provides a secure bridge for the desktop app to retrieve license keys following a successful purchase. This prevents the Polar Organization Access Token from being bundled within the macOS binary.
API Endpoint: /api/license
This endpoint maps a checkout_id to a granted license key.
| Parameter | Type | Description |
|---|---|---|
checkout_id | String | A UUID or a Polar client secret (polar_c_...) from the purchase redirect. |
Internal Logic:
- Checkout Verification: Validates the checkout status is
succeeded,confirmed, orcomplete. - Customer Identification: Extracts the
customer_idfrom the checkout record. - License Retrieval: Queries Polar for license keys associated with the customer and returns the first key with a
grantedstatus.
Sources: services/polar-license-lookup/api/license.js:15-62, services/polar-license-lookup/README.md:27-35
Native Swift Implementation
The desktop app manages licensing through three main layers: configuration, stateless service communication, and a stateful UI store.
PolarService
PolarService is a stateless client for Polar's customer-portal endpoints. These endpoints are public and only require the organization_id.
LicenseStore
The LicenseStore acts as a coordination layer, managing user-facing states and persistence.
Entitlement States:
checking: Initial state during launch.licensed: Full access granted.trial(daysLeft): Active trial period (default 14 days).trialExpired: Trial has ended; cleaning disabled.unlicensed: Default state for new users.revoked: Key was invalidated by the server.
Sources: apps/desktop/Sources/Crisp/Services/Licensing/LicenseStore.swift:18-35, apps/desktop/Sources/CrispCore/Licensing/PolarConfig.swift:35
Device Binding and Re-validation
Crisp uses device-bound activation if the Polar product configuration has limit_activations > 0.
- Activation: The app generates a label (e.g.,
Mac · <device_id_prefix>) and binds the key to the current device's unique ID. - Persistence: The
LicenseStorage(backed by Keychain) stores the key and the specificactivationID. - Re-validation: The app performs a weekly re-validation. If the key is revoked (e.g., due to a refund), the app transition to the
.revokedstate and locks cleaning functionality.
Sources: apps/desktop/Sources/Crisp/Services/Licensing/LicenseStore.swift:145-155, apps/desktop/Sources/Crisp/Services/Licensing/LicenseStore.swift:186-210
Build-time Configuration
Licensing features are controlled via build-time environment variables, allowing the feature to remain "dark" in standard builds.
| Info.plist Key | Env Variable | Description |
|---|---|---|
CrispLicensingEnabled | CRISP_LICENSING | Kill-switch; must be YES to enable UI and logic. |
CrispPolarOrgID | CRISP_POLAR_ORG_ID | The Polar Organization UUID. |
CrispPolarLookupURL | CRISP_POLAR_LOOKUP_URL | URL for the serverless lookup function. |
CrispPolarCheckoutURL | CRISP_POLAR_CHECKOUT_URL | Link to the Polar hosted checkout page. |
Sources: apps/desktop/build.sh:86-105, apps/desktop/Sources/CrispCore/Licensing/PolarConfig.swift:11-20
Summary
The Polar Licensing Integration provides a secure, subscription-based model for Crisp. It leverages a serverless proxy to protect sensitive API keys while providing a native macOS experience, including automated activation via the crisp://activate deep link and offline grace periods for periodic license validation.
Sources: CLAUDE.md:12-15, services/polar-license-lookup/README.md:1-10