Add Audio & Video Calling to Your Website or App
Integrate 1-on-1 voice calls, HD video consultations, and service-app calling workflows with PulseRTC in 3 steps—with prepaid minute billing and ephemeral STUN/TURN relay built in.
Get App ID & Secret
Sign up in the Developer Portal to get 1,000 free calling minutes, an App ID, and a server-only App Secret.
Mint Token on Your Backend
When two users start a call on your website/app, your backend calls POST /v1/rtc/token to fetch a short-lived room JWT and ICE TURN servers.
Join Room from Client SDK
Pass the token into @pulsertc/sdk (Web, React Native, or Flutter) to stream low-latency 48kHz audio & HD video.
// 1. Run this on your website/app backend (keep App Secret private)
app.post('/api/calls/join-token', async (req, res) => {
const response = await fetch('https://pulse.amiyogroup.com/v1/rtc/token', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'x-app-id': process.env.RTC_APP_ID, // e.g. prtc_...
'x-app-secret': process.env.RTC_APP_SECRET // secret stays on server
},
body: JSON.stringify({
roomName: `order-${req.body.bookingId}`,
identity: req.user.id,
displayName: req.user.name,
role: 'speaker'
})
});
if (response.status === 403) {
// Tenant minute balance exhausted or suspended
return res.status(403).json(await response.json());
}
// Returns { wsUrl, token, iceServers, roomName, identity, expiresAt }
return res.json(await response.json());
});import { PulseClient } from '@pulsertc/sdk';
// Point tokenEndpoint to YOUR backend route that returns { wsUrl, token, iceServers }
const client = new PulseClient({
appId: 'prtc_your_app_id',
tokenEndpoint: '/api/calls/join-token',
});
// Start a 1-on-1 or group HD Video + Audio Call in your website
const room = await client.joinRoom({
roomName: 'consultation-room-42',
identity: 'customer_104',
displayName: 'Riya Patel',
audio: true,
video: true, // set false for Voice-Only calling
});
// Listen for remote participants & attach audio/video elements
client.on('trackSubscribed', ({ track, participant }) => {
const el = track.attach();
document.getElementById('remote-media-grid')?.appendChild(el);
});
// In-call controls
await client.setMicrophoneEnabled(false); // mute mic
await client.setCameraEnabled(false); // toggle video
await client.leaveRoom();Verifies active tenant & prepaid balance (> 0 mins), mints a scoped LiveKit SFU JWT, and returns ephemeral Coturn STUN/TURN credentials.
Records metered participant-seconds, deducts tenant minute balance, and triggers call.completed / quota.low outbound webhooks.
Returns Call Detail Records (CDRs) per App ID, room, participant, and billed minutes.
Register HTTPS webhook receivers for call.completed and quota.low events signed with HMAC-SHA256.
Automated SFU participant_left minute metering and prepaid bundle top-up fulfillment.
Receive signed call.completed and quota.low notifications on your app server:
import crypto from 'node:crypto';
// Verify X-PulseRTC-Signature: t=17944...,v1=abcdef...
export function verifyWebhookSignature(rawBody, sigHeader, secret) {
const parts = Object.fromEntries(sigHeader.split(',').map((kv) => kv.split('=')));
const expected = crypto
.createHmac('sha256', secret)
.update(`${parts.t}.${rawBody}`)
.digest('hex');
return parts.v1 === expected;
}Tenant minute balance reached 0.00. Top up a bundle to resume token minting.
Account suspended by platform admin. Token generation is blocked until reactivated.
Unknown or revoked App ID/Secret. Generate or check credentials in /portal.
Per-minute API rate limit exceeded. Respect X-RateLimit-Reset header before retrying.