API Server Setup

Purpose and Scope

This page explains how to bring up the Cal.diy API service during a self-hosted installation. In this repository, the self-hosting installation guide starts from the whole monorepo: clone the project, install dependencies with Yarn, copy environment templates, generate a NextAuth secret, and build or start the application. The API-specific material then narrows that general setup to the versioned API service, which is a Nest.js application under the API workspace. Treat this page as the bridge between the broad installation flow and the concrete commands and runtime behavior used by API v2. Sources: apps/docs/content/installation.mdx, apps/api/v2/README.md

The API service is not just a single command; it depends on matching environment values, a reachable PostgreSQL-backed Prisma setup, local email support for development, and the runtime mode chosen by the process. The repository separates a lightweight API proxy from the API v2 Nest application. The proxy accepts traffic on one local port and forwards unversioned and versioned API paths to separate backend targets, while API v2 owns its own bootstrap, configuration, logging, Swagger generation in development, and serverless handler path. Sources: apps/api/index.js, apps/api/v2/src/main.ts

Relevant Source Files

  • apps/docs/content/installation.mdx — Provides the self-hosting installation baseline: prerequisites, clone and dependency steps, environment file setup, production build commands, and the warning to upgrade the database before production builds.
  • apps/api/v2/README.md — Documents API v2 local development, required environment synchronization, Mailhog, optional Prisma setup and seeding, run commands, dependency rebuild watch mode, and API v2 test commands.
  • apps/api/index.js — Defines the local API proxy process that forwards root API traffic to one service and /v2 traffic to the API v2 service.
  • apps/api/v2/src/main.ts — Contains the API v2 Nest.js entrypoint, local startup path, serverless handler, singleton Express server cache, bootstrap call, configuration lookup, logging, and Swagger generation behavior.

Core Primitives

The first primitive is the repository-level installation environment. The installation guide expects Node.js, Yarn, Git, and PostgreSQL, with Node.js version 18 recommended for compatibility. It also expects a root environment file copied from the example template, plus a generated secret stored as NEXTAUTH_SECRET. For API v2, that same secret must be present in both the root environment file and the API v2 environment file. This matters because authentication-related code must agree on the same signing secret across the web application and the API process. Sources: apps/docs/content/installation.mdx, apps/api/v2/README.md

The second primitive is the API v2 application itself. The README identifies it as a Nest.js project, and the entrypoint creates a Nest Express application from AppModule. The factory uses a Winston-backed logger configuration, then startup code calls the shared bootstrap function before listening locally or initializing the cached serverless instance. In development, the startup path reads configuration through Nest ConfigService, obtains the API port from the api.port config key, and generates Swagger output when the environment type is development. Sources: apps/api/v2/README.md, apps/api/v2/src/main.ts

The third primitive is the proxy layer. The API proxy is a small Node.js Connect server that creates two proxy middlewares. Requests mounted at the root are sent to http://localhost:3003, while requests mounted below /v2 are sent to http://localhost:3004. The proxy itself listens on port 3002. In local development, this allows a single API-facing port to route requests to different API implementations by path, so callers can use the versioned route shape without knowing the internal service port layout. Sources: apps/api/index.js

Setup Flow

Start with the normal self-hosting setup. Clone the repository, enter the project directory, and install dependencies. Then copy the root environment template to a real environment file and generate a strong secret for authentication. The installation documentation also calls out an app-store environment file for integration keys, which is relevant when API actions interact with installed apps or integration-backed behavior. For production builds, the docs instruct operators to build and start the monorepo with Yarn, while warning that the database should be upgraded before building for production. Sources: apps/docs/content/installation.mdx

git clone https://github.com/calcom/cal.diy.git
cd cal.diy
yarn
openssl rand -base64 32

Next configure API v2 itself. The API v2 README instructs developers to copy apps/api/v2/.env.example to apps/api/v2/.env. It then emphasizes that NEXTAUTH_SECRET must match between the root environment file and the API v2 environment file. Local API v2 development also expects Docker to be installed and running, and Mailhog must be available because API v2 uses it to send local email. The documented way to start that local email service is from the emails package using its development experience command. Sources: apps/api/v2/README.md

cd packages/emails
yarn dx

The API v2 local README also includes a database compatibility setup for a deployment license value. It asks for an entry in the Deployment table with a placeholder license key and matching CALCOM_LICENSE_KEY in the API v2 environment. Even when a self-hosted Cal.diy operator is primarily focused on local scheduling behavior, this step is part of the documented API v2 boot path and should be treated as required for that local service setup unless the surrounding code path has been intentionally changed. Optional Prisma commands are provided for generating the client, running migrations, and seeding data. Sources: apps/api/v2/README.md

cd packages/prisma
yarn prisma generate
yarn prisma migrate dev
yarn db-seed

Running the API Service

For normal API v2 development, run the documented development command from the API v2 workspace context. The README presents yarn dev as the primary startup command. Once the Nest entrypoint runs outside Vercel, it calls the local run() function, creates the Nest app, applies bootstrap behavior, reads the configured port, optionally generates Swagger output in development, and starts listening. If local startup fails before completion, the entrypoint logs the failure through the Nest logger and exits in the outer startup path. Sources: apps/api/v2/README.md, apps/api/v2/src/main.ts

cd apps/api/v2
yarn dev

There are two important alternatives. First, if the watched development process restarts because unrelated build or log files change while the web app is also running, the README recommends building and then starting without watch mode. Second, if Docker is not desired, the README provides a no-Docker development command. These are operational choices rather than different APIs: the same Nest entrypoint still owns application creation, bootstrap, configuration, and request handling, but the surrounding development scripts change how dependencies are prepared and watched. Sources: apps/api/v2/README.md, apps/api/v2/src/main.ts

cd apps/api/v2
yarn dev:build
yarn start
 
# Or run without Docker
yarn dev:no-docker

Runtime Behavior and Deployment Shape

The entrypoint has two runtime shapes. When the process is not running in Vercel, local startup begins automatically. When it is running as a serverless handler, the default export receives the request and response, obtains a cached Express instance from the NestServer singleton, reparses query strings with qs to preserve array-style query parameters, and delegates the request to the cached Express server. That cache is deliberate: the class comment says it ensures the Nest.js application is initialized only once per container lifecycle. Sources: apps/api/v2/src/main.ts

Production mode sets TRIGGER_VERSION from the imported trigger version before the server starts. This is a small but useful signal that the API process changes selected environment state based on NODE_ENV. The same file also distinguishes development behavior through the config service: Swagger generation is only invoked when the configured environment type is development. Together, these branches show that environment configuration is part of the API server contract, not merely an external deployment concern. Sources: apps/api/v2/src/main.ts

API Proxy Routing Reference

ComponentLocal port or routeBehavior
API proxy server3002Starts an HTTP server with Connect middleware.
API v1 proxy targethttp://localhost:3003Receives requests mounted at /.
API v2 proxy targethttp://localhost:3004Receives requests mounted at /v2.
API v2 Nest appConfig value api.portLocal Nest startup listens on the configured API port.

Use the proxy when you need the monorepo’s local API routing shape rather than contacting the API v2 port directly. Use the API v2 workspace commands when you are developing or debugging the Nest application itself. If platform packages such as platform libraries, constants, enums, utilities, or types change, the README warns that API v2 may need a restart so it rebuilds and picks up those dependency changes. It also provides a watch command that rebuilds those platform dependencies in another terminal while API v2 runs. Sources: apps/api/index.js, apps/api/v2/README.md

yarn run dev:build:watch

Verification and Next Steps

After startup, verify the service at the level that matches your task. For API implementation work, run the API v2 test commands documented in the README: unit tests, end-to-end tests, a specific end-to-end test file in watch mode, or coverage. For installation validation, confirm that the database was migrated or seeded as intended, the root and API v2 secrets match, Mailhog is running when local email is needed, and the proxy routes match the port assumptions in your client or web app configuration. Sources: apps/api/v2/README.md, apps/api/index.js

Read the broader installation pages before treating the API server as production-ready. The installation guide’s production build instructions require database upgrade attention before building, and the API v2 README is primarily framed as local development guidance. For a complete self-hosted deployment, pair this page with environment and URL configuration, database migration guidance, cron job setup, and API v2 authentication details. Those pages explain the surrounding services that determine whether the API server can accept authenticated requests and coordinate with the rest of the Cal.diy application. Sources: apps/docs/content/installation.mdx, apps/api/v2/README.md