Skip to content

3. Choose your setup ​

Make these decisions before writing code. Each row says what to pick and why.

3.1 What kind of calling product are you? ​

Your productPickWhat it means in Calloop
A support / sales team answering customers (a help desk, a clinic's front desk)Contact center (steps)Shared lines with a queue; agents go Available to receive calls; IVR menus, transfers, supervisor whisper and barge
A platform serving many businesses, each with its own teamContact center per business (steps)One tenant per business, set up by your backend when the business turns calling on
Each end user has their own number (an eSIM or virtual-number app, a "business phone in your pocket")Personal lines (steps)Each user is an agent who owns one line; a call to the number rings only that user, on all their devices
Both (users with their own numbers, plus your own support line)Both, usually in two tenantsLines decide: a line with a queue is shared, a line with an owner is personal, and one tenant may hold both. But the settings in §3.4 are per tenant: if end users must not see the board, or your support team needs whisper and barge, put the support team in its own tenant
Click-to-call from your CRM (outbound mainly)Outbound (steps)Your backend creates the call; the agent's app connects it (§4.7)

3.2 How many tenants? ​

Your productPick
You serve many separate businesses (multi-tenant SaaS, e.g. a booking platform for salons)One tenant per business. Each business's agents, lines, queues and calls are isolated. Use your business id as the tenant ref
One product whose users are individuals (e.g. an eSIM app)One tenant for the whole product. Every end user is an agent in it; your internal staff are its supervisors

3.3 Which channel(s)? ​

ChannelPick it whenYou need
WhatsApp CallingYour customers already reach you on WhatsAppA Meta WhatsApp Business number with calling enabled: its phone_number_id and a system-user access token
SIP (phone numbers)Customers dial a normal phone number, or your users need real numbersA carrier trunk (yours or the operator's) and DIDs on it. The carrier authenticates by IP (no registration) and sends its SDP offer in the INVITE (limits)

WhatsApp webhook: direct or forwarded?

OptionPick it when
Forward (POST /v1/webhooks/whatsapp/forward with your API key)Recommended for most products. Your Meta app's webhook already points at your backend (for messages); forward the same payload to Calloop. Calloop only processes calls on your own lines
Direct (Meta posts to Calloop's /webhooks/whatsapp)Calloop's operator runs the Meta app and has configured its app secret on Calloop

3.4 Who may see whom, and listen? ​

Tenant settings (set with PUT /v1/tenants/{ref}):

SettingContact centerPersonal lines
team_viewtrue: agents see the team board, queues and colleagues' statusesfalse: an end user must only ever see their own calls
monitoring.modes["listen", "whisper", "barge"]: supervisors coach and step in["listen"]: internal staff may listen, never be heard
auto_offlineOptional, off by default: { "enabled": true, "missed_threshold": 3 } takes an agent offline after 3 missed offers in a rowNot relevant (personal lines ring the owner regardless of availability)

Allowing whisper or barge (any mode other than listen) also sends every personal-line call through a media-server room instead of the cheaper direct path (§4.2).

3.5 Recording ​

Turn it on for your whole account (PUT /v1/recording-policy { "enabled": true }), a tenant (settings.recording.enabled) or one line (recording_enabled: true): the nearest level that chooses wins, and enforced on the account or a tenant stops the levels below from choosing. The file is a stereo Ogg Opus recording (customer left, agent right), stored where the platform's operator chose (Calloop's servers or their S3 bucket). A personal line's call keeps the cheap direct path when it is recorded: copies of both sides are recorded, the call itself is untouched. recording.completed says when a recording is ready, recording.failed that a call won't have one. Fetch it with a short-lived URL (GET /v1/calls/{id}/recording). Old recordings move to cheaper storage and are deleted on the platform's schedule, or the tenant's own: settings.recording.cold_after_days and settings.recording.retention_days.

3.6 Which client SDK? ​

Your appUseInstall
Web app (any framework)JS SDK @calloop/agent-sdk (README)Not on npm yet: depend on it from the Calloop repo (sdk/agent-js)
React web appReact bindings @calloop/agent-react on top of the JS SDK (README)Same: from the repo (sdk/agent-react)
Flutter app (Android / iOS)Dart SDK calloop_agent (README), with native_calls.dart for the phone's own call screen (Android only; on iOS your app handles PushKit/CallKit, see §7)Not on pub.dev: a git or path dependency on sdk/agent-dart
Anything else (native iOS/Android, desktop)Implement the protocol directly: Socket.IO + WebRTC (agent-protocol.md)—
A server-side bot or testThe JS SDK in Node, with @roamhq/wrtc for WebRTCFrom the repo

3.7 Push ​

PlatformWhat Calloop sendsCredentials you give Calloop
AndroidFCM data message (call.incoming, call.cancelled)Firebase service account JSON
iOSAPNs VoIP push (PushKit → CallKit), plus an FCM bannerAPNs .p8 key, key id, team id, bundle id
WebOneSignalOneSignal app id and REST key

You register each device's token from your backend (PUT …/agents/{ref}/push-tokens/{deviceId}). A push never carries call details beyond ids and the caller: the app connects and syncs.

Calloop — the call engine behind your product.