Secure voice and video calling, managed TURN, call lifecycle APIs, telemetry and usage billing — over plain HTTPS and the WebRTC already in your app. No SDK to install, no Firebase, no vendor account, and your App Secret never leaves your server.
₹100 free credit to start · then ₹0.10/min audio, ₹0.40/min video · billing details
// No SDK, no Firebase. Just fetch + WebRTC.
const {sessionToken} = await post(
'/v1/session/exchange',
{appId, accessToken},
);
// One long poll delivers every inbound event.
const {events} = await get(
'/v1/events?cursor=0&wait=25',
);
// Place a call.
await post('/v1/calls', {
toUserId: 'user_42',
callType: 'video', offer,
});
Monitor connection rates, call durations, and setup times instantly across all your apps. Spot ICE failures and connection drops before your users report them.
Understand exactly how your network traffic flows. VACT breaks down WebRTC connections by direct P2P (host), Server Reflexive (STUN), or Relay (TURN).
Optimize your TURN server placements and significantly reduce bandwidth costs by analyzing regional fallback rates.
Adding voice & video calling to your app, answered.
VACT is a programmable voice and video calling API and SDK for adding one-to-one WebRTC audio and video calls to web, Flutter, React, React Native, Node, Python and PHP apps. Signalling and TURN relays are fully managed, so you don't run a signalling server, and billing is usage-based per minute.
Install the SDK (vact_sdk on pub.dev for Flutter, @firstlogicmetalab/client on npm for web/React, @firstlogicmetalab/react-native for React Native), mint a one-time access token on your backend with your App Secret, call connect, then call or accept. No Firebase and no signalling server are required.
No. VACT manages WebRTC signalling and TURN for you. Your app speaks plain HTTPS plus the WebRTC already in the runtime, and your backend only mints short-lived access tokens. Nothing else to host.
VACT is a lightweight, developer-first option for one-to-one voice and video: zero client dependencies, managed TURN, a plain REST API with an OpenAPI spec, SDKs for Flutter, React, React Native, Node, Python and PHP, transparent per-minute pricing, and a free tier to start.
Client SDKs for web (any framework), React, React Native and Flutter; server SDKs for Node, Python and PHP; and a plain REST API for everything else. The whole client protocol is documented, with runnable examples for Node and Firebase backends.
It's free to start with ₹100 of calling credit and no card required. After that it's usage-based: audio and video calls are billed per minute at rates you can see per app. You only pay for what you use.
The deployed dashboard discovers its public Firebase web configuration at runtime. For local development only, you may paste a Firebase web config here. Sign in with Google—admins see all apps; client users see only apps assigned to their email.
Setup: enable Google sign-in + authorized domains in Firebase Console. "All apps" uses a collection-group query on call_logs — enable the collection-group index for createdAt if Firestore asks (the error message includes a one-click link). Inside the Claude preview the sandbox may block Firebase — deploy the file for live use; demo mode works everywhere.
Four steps from signup to a live call. Your progress is saved on this device.
| Period | Amount | Paid | Due | Status | Due date |
|---|
| When | Type | Description | Amount | Status |
|---|
| Month | Audio | Video | Calls | Charge |
|---|
| App | Audio min | Video min | Rates A/V per min | Billed | Wallet | Billed due |
|---|
| Started | App | Caller → Callee | Type | Setup | Duration | Route | Network | End reason |
|---|---|---|---|---|---|---|---|---|
| Loading… | ||||||||
Docs live at apps/{appId}/call_logs/{callId} · usage aggregates at apps/{appId}/usage/{all|YYYY-MM} · money at apps/{appId}/{wallet,bills,transactions} — all written only by Cloud Functions. Admins record offline payments through the manual-credit API, never by writing documents.
Up to 4 apps per account. Your email is already verified through Google sign-in.
Next: mint a token from your backend · pick your client platform
Run this on your machine — a 201 with an accessToken means both keys work.
Next: mint a token from your backend ·
pick your client platform
Packages:
Flutter ·
JavaScript ·
Node server ·
Python ·
PHP
A blocked address is refused before any request is processed. Only the hash of an IP is stored. Addresses are shared behind mobile carriers and VPNs, so a block can affect unrelated users and is easily evaded — prefer app suspension for non-payment.
| IP hash | Reason | App | Blocked | |
|---|---|---|---|---|
| Not loaded | ||||
Blocks every address an app has connected from. Reserved for a suspended, non-paying tenant — apps become eligible 15 days after suspension. This is blunt: it can block unrelated users behind the same address and will not stop someone who switches network.
| App | Calls | Minutes | Connected | Relay | Status |
|---|---|---|---|---|---|
| Open to load | |||||