3.7 KiB
3.7 KiB
API Reference
Authentication
curl -X POST 'https://rtc.live/v1/apps/${CALLS_APP_ID}/sessions/new' \
-H "Authorization: Bearer ${CALLS_APP_SECRET}"
Core Concepts
Sessions: PeerConnection to Cloudflare edge
Tracks: Media/data channels (audio/video/datachannel)
No rooms: Build presence via track sharing
Client Libraries
PartyTracks (Recommended): Observable-based client library for production use. Handles device changes, network switches, ICE restarts automatically. Push/pull API with React hooks. See patterns.md for full examples.
npm install partytracks @cloudflare/calls
Raw API: Direct HTTP + WebRTC for custom requirements (documented below).
Endpoints
Create Session
POST /v1/apps/{appId}/sessions/new
→ {sessionId, sessionDescription}
Add Track (Publish)
POST /v1/apps/{appId}/sessions/{sessionId}/tracks/new
Body: {
sessionDescription: {sdp, type: "offer"},
tracks: [{location: "local", trackName: "my-video"}]
}
→ {sessionDescription, tracks: [{trackName}]}
Add Track (Subscribe)
POST /v1/apps/{appId}/sessions/{sessionId}/tracks/new
Body: {
tracks: [{
location: "remote",
trackName: "remote-track-id",
sessionId: "other-session-id"
}]
}
→ {sessionDescription} (server offer)
Renegotiate
PUT /v1/apps/{appId}/sessions/{sessionId}/renegotiate
Body: {sessionDescription: {sdp, type: "answer"}}
Close Tracks
PUT /v1/apps/{appId}/sessions/{sessionId}/tracks/close
Body: {tracks: [{trackName}]}
→ {requiresImmediateRenegotiation: boolean}
Get Session
GET /v1/apps/{appId}/sessions/{sessionId}
→ {sessionId, tracks: TrackMetadata[]}
TypeScript Types
interface TrackMetadata {
trackName: string;
location: "local" | "remote";
sessionId?: string; // For remote tracks
mid?: string; // WebRTC mid
}
WebRTC Flow
// 1. Create PeerConnection
const pc = new RTCPeerConnection({
iceServers: [{urls: 'stun:stun.cloudflare.com:3478'}]
});
// 2. Add tracks
const stream = await navigator.mediaDevices.getUserMedia({video: true, audio: true});
stream.getTracks().forEach(track => pc.addTrack(track, stream));
// 3. Create offer
const offer = await pc.createOffer();
await pc.setLocalDescription(offer);
// 4. Send to backend → Cloudflare API
const response = await fetch('/api/new-session', {
method: 'POST',
body: JSON.stringify({sdp: offer.sdp})
});
// 5. Set remote answer
const {sessionDescription} = await response.json();
await pc.setRemoteDescription(sessionDescription);
Publishing
const offer = await pc.createOffer();
await pc.setLocalDescription(offer);
const res = await fetch(`/api/sessions/${sessionId}/tracks`, {
method: 'POST',
body: JSON.stringify({
sdp: offer.sdp,
tracks: [{location: 'local', trackName: 'my-video'}]
})
});
const {sessionDescription, tracks} = await res.json();
await pc.setRemoteDescription(sessionDescription);
const publishedTrackId = tracks[0].trackName; // Share with others
Subscribing
const res = await fetch(`/api/sessions/${sessionId}/tracks`, {
method: 'POST',
body: JSON.stringify({
tracks: [{location: 'remote', trackName: remoteTrackId, sessionId: remoteSessionId}]
})
});
const {sessionDescription} = await res.json();
await pc.setRemoteDescription(sessionDescription);
const answer = await pc.createAnswer();
await pc.setLocalDescription(answer);
await fetch(`/api/sessions/${sessionId}/renegotiate`, {
method: 'PUT',
body: JSON.stringify({sdp: answer.sdp})
});
pc.ontrack = (event) => {
const [remoteStream] = event.streams;
videoElement.srcObject = remoteStream;
};