Skip to main content

Architecture

Ringee is composed of 3 main services backed by a set of external services. The main services communicate through HTTP and Temporal, and connect to external services for data storage, telephony, auth, and payments.
  • Frontend — Web interface for managing calls, contacts, and analytics.
  • Backend — REST API that handles all business logic and integrations.
  • Orchestrator — Temporal worker that runs durable background jobs and schedules.

Frontend

A single Next.js application on port 4200, using the App Router with feature-based organization:
  • the marketing site;
  • the authenticated dashboard — calls, contacts, campaigns, analytics, numbers, billing;
  • the browser-based dialer, powered by Telnyx WebRTC.
It uses Clerk for authentication and talks to the backend API for all operations.

Backend

The backend is the brain of Ringee — a NestJS application on port 3000 with a global /api prefix. It:
  • handles all REST API requests, protected by a Clerk auth guard;
  • manages Telnyx call control, number purchasing and WebRTC credentials;
  • processes Stripe webhooks for payments, credits and subscriptions;
  • handles Clerk webhooks for user and organization management;
  • serves the Public API for CRM integrations;
  • serves the MCP server for AI assistants;
  • serves the Dialer SDK endpoints under /api/v1/sdk;
  • starts durable workflows on Temporal.

Orchestrator

A separate process (apps/orchestrator) that runs the Temporal worker. It executes the workflows the backend starts and owns the periodic schedules:
  • webhook delivery drains and retries;
  • callback, reminder and retry pollers;
  • CRM synchronization drains;
  • recording and transcription processing;
  • push notifications via Firebase Cloud Messaging.
Workflow names and inputs are shared through a contracts file, so the backend and the orchestrator never drift.
Temporal replaced the earlier Redis pub/sub worker. Redis is still used for caching and session state.

Shared packages

Ringee is a pnpm workspaces monorepo. Business logic lives in shared packages rather than in any single app: This is why the Public API, the MCP server, the CLI and the Dialer SDK all behave identically: they are different entry points into the same service layer.

External Services

Multi-tenancy

Users belong to organizations through memberships. Most entities — calls, contacts, numbers, credits, campaigns — carry both a userId and an optional organizationId, so a user’s personal data and their organizations’ data stay separate. Every entry point respects this. The dashboard, the Public API, the MCP server and the Dialer SDK all resolve the same ownership context before reading or writing.

Building on Ringee

Ways to build

Which integration surface fits your use case

Add a provider

Integrate another telephony provider