calcom/cal.com
Credential
Encrypted third-party credentials. Every installed app (calendar, video, payment, CRM, ...) has at least one Credential row. The key JSON column is encrypted with CALENDSO_ENCRYPTION_KEY and must never appear in API responses — AGENTS.md calls this out as one of the few hard prohibitions in the project.
Schema highlights
Credential:
id,userId?,teamId?type— the integration's "type" string (e.g.,google_calendar,office365_calendar,daily_video,stripe_payment)key(JSON, encrypted) — access tokens, refresh tokens, expiry, vendor-specific configappId?→Apptable (the App Store entry)delegationCredentialId?— when this is delegated from a system-wide credentialinvalidboolean — set when the credential failed and needs reauthorizationsubscriptionId?— push-notification subscription (if any)subscriptionExpiresAt?
Encryption
packages/lib/crypto.ts exposes encrypt(...) / decrypt(...) using AES-256-CBC with CALENDSO_ENCRYPTION_KEY (set via openssl rand -base64 24 per the README). Every read of key calls decrypt; every write calls encrypt. The encrypted blob is stored as JSON.
Where it lives in code
| Concern | File |
|---|---|
| Domain | packages/features/credentials/ |
| Delegation | packages/lib/delegationCredential.ts, packages/features/credentials/ |
| App-store interaction | packages/app-store/<provider>/api/_postAdd.ts (or similar) |
Calendar adapter base (uses key for OAuth refresh) |
packages/lib/CalendarService.ts |
| Per-app key schema validation | packages/app-store/apps.keys-schemas.generated.ts (DO NOT EDIT) |
OAuth refresh
When an adapter calls a vendor API and gets a 401:
BaseCalendarService(or category-equivalent) decrypts the credential'skey.- Calls the vendor's refresh endpoint with the refresh token.
- Re-encrypts and writes back the new
key. - Retries the original request.
Failed refreshes set invalid = true. The dashboard surfaces these as "Reconnect" prompts.
Delegation
Some integrations support system-wide credentials (e.g., Google Workspace domain-wide delegation, where one service-account key covers many users). These live in a separate flow:
delegationCredentialIdonCredentialpoints to the upstream system-wide credential.packages/lib/delegationCredential.tsresolves the effective credentials at use time.
Security rules
AGENTS.md Don'ts:
Never expose
credential.keyfield in API responses or queries.
In practice this means:
- Repositories must use
selectand explicitly omitkeyunless the caller is the adapter itself. - Audit logs and Sentry events redact the
keyfield viapackages/lib/redactSensitiveData.ts. - Frontend types for credentials don't include
key.
Consumers
- All app-store adapters
- App Store install / uninstall flows
- Calendar federation, video providers, payment services, CRMs
- API v2
credentialsmodule
Related pages
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.