Quick start
Three steps from an empty project to people talking in a room.
Get your App ID and App Certificate
Sign up free (10,000 free minutes) or log in to your dashboard. Each app has an App ID, an App Certificate and a region URL. The App Certificate is a secret: it goes on your server and nowhere else.
Add a token endpoint to your server
Your backend signs a short-lived access token for a signed-in user and one room, with our token library for Node or Go. No Gravix service is called to make a token.
Join from your app
Install the SDK for your platform: flutter pub add gravix_rtc, or npm install gravix-rtc for the web. It asks your endpoint for a token, then connects to the room with it. Mic, camera and remote video are a few lines from there.
Access tokens
An access token lets one user into one room for a limited time. It is a signed JWT that carries the room, the user's identity and what they may do (for example publish audio and video, or only listen). Gravix checks the signature when the user joins.
Tokens are signed with your App Certificate. Whoever holds it can let anyone into any of your rooms, and that usage is billed to you. So:
- Keep the App Certificate on your server, in an environment variable or a secrets store. Never put it in app code, a mobile build or a web bundle.
- Sign a token only for a user your backend has already authenticated, and take their identity from your own session.
- Decide on the server whether a user may publish or only listen.
- Keep tokens short-lived. They last 6 hours unless you set another time, and 24 hours at most.
Your token endpoint
Install gravix-rtc-token from npm (Node 18+, Deno, Bun and edge runtimes) or use gravix-token-go (Go 1.21+). Both take the same options. The endpoint below is all a backend needs for joining.
// server.ts (your backend, Node 18+). This file never ships inside an app.
import express from 'express';
import { createToken } from 'gravix-rtc-token';
const APP_ID = process.env.GRAVIX_APP_ID!; // from your dashboard
const APP_CERTIFICATE = process.env.GRAVIX_APP_CERTIFICATE!; // server only, never in an app
const REGION_URL = process.env.GRAVIX_URL!; // wss://YOUR-REGION-URL
const app = express();
app.use(express.json());
// requireUser is your own login check: the identity comes from YOUR session,
// never from the request body.
app.post('/rtc/token', requireUser, async (req, res) => {
const room = req.body?.room;
if (typeof room !== 'string' || !/^[\w.-]{1,64}$/.test(room)) {
return res.status(400).json({ error: 'invalid room' });
}
const token = await createToken(APP_ID, APP_CERTIFICATE, {
room, // the library adds your App ID prefix
identity: req.user.id,
name: req.user.name,
canPublish: true, // false = listen only; decide it here, not in the app
ttlSeconds: 60 * 60, // short-lived: 1 hour
});
res.json({ token, url: REGION_URL });
});
app.listen(3000);// token.go (your backend, Go 1.21+). gravixtoken is the gravix-token-go package.
func tokenHandler(w http.ResponseWriter, r *http.Request) {
user, ok := currentUser(r) // your own login check
if !ok {
http.Error(w, "sign in first", http.StatusUnauthorized)
return
}
var body struct {
Room string `json:"room"`
}
if err := json.NewDecoder(r.Body).Decode(&body); err != nil || body.Room == "" {
http.Error(w, "invalid room", http.StatusBadRequest)
return
}
// The App Certificate stays in the server's environment.
jwt, err := gravixtoken.New(os.Getenv("GRAVIX_APP_ID"), os.Getenv("GRAVIX_APP_CERTIFICATE")).
Room(body.Room).
Identity(user.ID).
Name(user.Name).
CanPublish(true). // false = listen only
TTL(time.Hour). // short-lived
ToJWT()
if err != nil {
http.Error(w, "could not sign", http.StatusInternalServerError)
return
}
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(map[string]string{
"token": jwt,
"url": os.Getenv("GRAVIX_URL"), // wss://YOUR-REGION-URL
})
}The SDKs post { room, identity, name, can_publish } to your endpoint and expect { token, url } back, where url is your region URL from the dashboard. Treat the request body as a wish, not a fact: the identity and the publish right are yours to set.
Join from the app
The app never sees your App Certificate. It points the SDK at your endpoint and joins.
import 'package:gravix_rtc/gravix_rtc.dart';
// One provider per signed-in user. It caches each token until it is about to expire.
final tokens = GravixTokenProvider.endpoint(
Uri.parse('https://YOUR-BACKEND/rtc/token'),
headers: {'Authorization': 'Bearer $sessionJwt'}, // your app's own login session
);
final room = GravixRoomService();
Future<void> join(String roomId, String userId, String name) async {
room.onRemoteVideoTrack = (uid, track) {
// show it with VideoTrackRenderer(track)
};
final ok = await room.connectWithTokenProvider(
tokenProvider: tokens,
request: GravixTokenRequest(
room: roomId,
identity: userId,
name: name,
canPublish: true,
),
publishMic: true,
enableVideo: true,
);
if (!ok) {
// room.lastTokenError is set when your token endpoint failed
}
}
Future<void> leave() => room.disconnect();import { Room, RoomEvent, GravixTokenProvider, connectWithTokenProvider } from 'gravix-rtc';
// Calls YOUR backend with the user's session cookie. Tokens are cached until they expire.
const tokens = GravixTokenProvider.endpoint('https://YOUR-BACKEND/rtc/token', {
credentials: 'include',
});
const room = new Room();
const stage = document.getElementById('stage')!;
room
.on(RoomEvent.TrackSubscribed, (track) => {
stage.appendChild(track.attach()); // a <video> or <audio> element
})
.on(RoomEvent.TrackUnsubscribed, (track) => {
track.detach().forEach((el) => el.remove());
});
export async function join(roomId: string, userId: string, name: string) {
await connectWithTokenProvider(room, {
tokenProvider: tokens,
request: { room: roomId, identity: userId, name },
});
await room.localParticipant.setMicrophoneEnabled(true);
await room.localParticipant.setCameraEnabled(true);
}
export const leave = () => room.disconnect();Android and iOS apps use the Flutter SDK today. Platform setup (permissions, background audio) is on the SDKs page.
SDKs
One room model on every platform. Pick yours for install steps, platform setup and a complete join example.
Flutter
gravix_rtc
Calls, video and live rooms for Flutter apps on Android and iOS.
flutter pub add gravix_rtcWeb
gravix-rtc
The browser SDK for web apps, with TypeScript types.
npm install gravix-rtcAndroid
Android via Flutter
Build Android apps with gravix_rtc. Android 7.0 (API 24) and later.
iOS
iOS via Flutter
Build iOS apps with gravix_rtc. iOS 13 and later.
Guides
- Quick start: live streaming. A host goes live and an audience watches, with full Flutter and React samples.
- Integrate with an AI coding assistant. A copy-paste prompt and the exact contract for Claude Code, Cursor or Copilot. Plain text for assistants:
/llms.txt.
Beauty filter and Studio
The real-time beauty filter is included free with every subscription, and Gravix Studio lets you design camera looks in the browser. Read what each one does before you wire it into your app.
Get help
Stuck on a token, a permission or a platform build? Talk to a person.
- Call +880 1703-449000
- WhatsApp +880 1703-449000
- Email sales@gravixcloud.com
