Agora RTM token — mobil ve web
RTM token alma ve yenileme entegrasyonu
Agora RTM Token - Mobile/Web Integration
Migration rehberi
Yapılandırma sırası için Migration şablonu. Yeni düzenlemelerde Amaç → Önkoşullar → Endpoint → Request/Response → Hata kodları → Client adımları → İlgili sayfalar bölümlerini tercih edin.
Bu doküman, mobil ve web istemcilerinin canlı yayın join response'undan Agora RTM token alıp agora-rtm-sdk ile login olması için gereken minimum entegrasyon bilgisini verir.
Kapsam
- Ayrı RTM token endpoint'i yoktur.
- RTM token sadece mevcut live stream join endpoint'leriyle döner.
- Frontend tarafında token üretilmez.
- App Certificate veya secret hiçbir client build'ine konmaz.
POST /api/v1/live-stream/createRTM token dönmez. Yayın sahibi yayına girmek içinjoin-as-creatorçağırdığında RTM token alır.
Endpointler
Auth tüm endpointlerde zorunludur:
Authorization: Bearer <JWT>Audience:
POST /api/v1/live-stream/join
Content-Type: application/json
{
"liveStreamId": "65f000000000000000000001",
"role": "audience"
}Creator:
POST /api/v1/live-stream/join-as-creator
Content-Type: application/json
{
"liveStreamId": "65f000000000000000000001"
}Guest:
POST /api/v1/live-stream/join-as-guest
Content-Type: application/json
{
"liveStreamId": "65f000000000000000000001"
}Response
Backend standart response wrapper döner. İstemcinin kullanacağı alanlar data içindedir.
{
"isSuccess": true,
"statusCode": 201,
"data": {
"liveStream": {
"id": "65f000000000000000000001",
"channelName": "stream-channel"
},
"agora": {
"appId": "agora-app-id",
"channelName": "stream-channel",
"token": "rtc-token",
"uid": 123456,
"role": "audience",
"expiresAt": "2026-05-20T13:00:00.000Z"
},
"rtm": {
"appId": "agora-app-id",
"channelName": "stream-channel",
"userId": "65f000000000000000000002",
"token": "rtm-token",
"expiresAt": "2026-05-20T13:00:00.000Z"
}
},
"errors": [],
"timestamp": "2026-05-20T12:00:00.000Z"
}Kullanım:
- RTC join için
data.agora.appId,data.agora.channelName,data.agora.token,data.agora.uid. - RTM login için
data.rtm.appId,data.rtm.userId,data.rtm.token. - RTM channel/message akışı için
data.rtm.channelName. - Token süre kontrolü için
data.rtm.expiresAt.
TypeScript Tipleri
type BaseResponse<T> = {
isSuccess: boolean;
statusCode: number;
data: T;
errors: string[];
timestamp: string;
};
type AgoraRtcToken = {
appId: string;
channelName: string;
token: string;
uid: number;
role: "host" | "guest" | "audience";
expiresAt: string;
};
type AgoraRtmToken = {
appId: string;
channelName: string;
userId: string;
token: string;
expiresAt: string;
};
type LiveStreamJoinResponse = BaseResponse<{
liveStream: unknown;
agora: AgoraRtcToken;
rtm: AgoraRtmToken;
}>;Mobil Kullanım Akışı
- Kullanıcı yayına girmeden önce rolüne göre join endpoint'ini çağır.
- Response'tan
data.agoraile RTC oturumunu başlat. - Response'tan
data.rtmile RTM client login işlemini yap. - RTM login başarılıysa
data.rtm.channelNamekanalına katıl veya signalıng mesaj akışını başlat. - Ekrandan çıkışta RTM channel leave ve RTM logout çağır.
Örnek:
const joinResponse = await api.joinLiveStream({ liveStreamId, role: "audience" });
const { agora, rtm } = joinResponse.data;
await rtcClient.join(agora.appId, agora.channelName, agora.token, agora.uid);
await rtmClient.login({
uid: rtm.userId,
token: rtm.token,
});
const rtmChannel = await rtmClient.createChannel(rtm.channelName);
await rtmChannel.join();Web Kullanım Akışı
Web tarafında aynı response alanları kullanılmalıdır. Token localStorage gibi kalıcı alanlarda tutulmamalı, sayfa oturumu, React state veya stream orchestration service içinde saklanmalıdır.
Paket
Web client tarafında RTC için agora-rtc-sdk-ng, RTM için agora-rtm-sdk kullanılmalıdır.
npm install agora-rtm-sdkRTM Service
RTM client sadece browser tarafında initialize edilmelidir. Next.js kullanılıyorsa service içinde dynamic import kullanmak SSR hatalarını engeller.
type AgoraRtmConfig = {
appId: string;
channelName: string;
userId: string;
token: string;
expiresAt: string;
};
type AgoraRtmMessageHandler = (message: unknown, memberId: string) => void;
export class AgoraRtmService {
private client: any | null = null;
private channel: any | null = null;
async login(config: AgoraRtmConfig, onMessage?: AgoraRtmMessageHandler) {
if (typeof window === "undefined") return;
if (new Date(config.expiresAt).getTime() <= Date.now()) {
throw new Error("Agora RTM token expired");
}
await this.logout();
const AgoraRTM = await import("agora-rtm-sdk");
this.client = AgoraRTM.default.createInstance(config.appId);
await this.client.login({
uid: config.userId,
token: config.token,
});
this.channel = this.client.createChannel(config.channelName);
if (onMessage) {
this.channel.on("ChannelMessage", onMessage);
}
await this.channel.join();
}
async sendChannelMessage(text: string) {
if (!this.channel) return;
await this.channel.sendMessage({ text });
}
async logout() {
if (this.channel) {
await this.channel.leave().catch(() => undefined);
this.channel = null;
}
if (this.client) {
await this.client.logout().catch(() => undefined);
this.client = null;
}
}
}
export const agoraRtmService = new AgoraRtmService();Join Response ile RTC + RTM Başlatma
const response = await fetch(`${API_BASE_URL}/api/v1/live-stream/join`, {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${accessToken}`,
},
body: JSON.stringify({ liveStreamId, role: "audience" }),
});
const payload: LiveStreamJoinResponse = await response.json();
const { agora, rtm } = payload.data;
await rtcClient.join(agora.appId, agora.channelName, agora.token, agora.uid);
await agoraRtmService.login(rtm, (message, memberId) => {
console.log("RTM channel message", { message, memberId });
});Creator ve guest için aynı service kullanılmalıdır. Tek fark endpoint seçimidir:
const creatorResponse = await api.post<LiveStreamJoinResponse>(
"/api/v1/live-stream/join-as-creator",
{ liveStreamId },
);
const guestResponse = await api.post<LiveStreamJoinResponse>(
"/api/v1/live-stream/join-as-guest",
{ liveStreamId },
);React Hook Örneği
import { useCallback, useEffect, useRef } from "react";
export function useAgoraRtm() {
const joinedRef = useRef(false);
const joinRtm = useCallback(async (rtm: AgoraRtmConfig) => {
await agoraRtmService.login(rtm, (message, memberId) => {
console.log("RTM message received", { message, memberId });
});
joinedRef.current = true;
}, []);
const leaveRtm = useCallback(async () => {
joinedRef.current = false;
await agoraRtmService.logout();
}, []);
useEffect(() => {
return () => {
if (joinedRef.current) {
void agoraRtmService.logout();
}
};
}, []);
return { joinRtm, leaveRtm };
}Stream Lifecycle Entegrasyonu
Web uygulamasındaki stream lifecycle akışı şu sırayı takip etmelidir:
join,join-as-creatorveyajoin-as-guestendpoint'i çağrılır.data.agoraile RTC channel join yapılır.data.rtmile RTM login ve channel join yapılır.- Kullanıcı ekrandan çıkarken önce RTM channel leave/logout, sonra RTC leave/track cleanup çalışır.
Örnek lifecycle parçası:
const { agora, rtm, liveStream } = joinResponse.data;
await streamOrchestrator.initializeStream({
streamId: liveStream.id,
channelName: agora.channelName,
token: agora.token,
uid: agora.uid,
appId: agora.appId,
role: StreamRole.AUDIENCE,
broadcasters: mapBroadcasters(agora.broadcasters, liveStream.creator),
streamData: liveStream,
userId: rtm.userId,
});
await agoraRtmService.login(rtm);Cleanup:
await agoraRtmService.logout();
await streamOrchestrator.cleanupStream();Token Süresi ve Hata Yönetimi
rtm.expiresAtgeçmişse RTM login denemesi yapılmamalıdır.- RTM login token expired hatası alırsa kullanıcıya yeniden yayına giriş akışı başlatılmalıdır.
- RTM token kısa ömürlüdür; uygulama kalıcı storage'a yazmamalıdır.
agora.uidilertm.userIdaynı tip değildir: RTC için numericuid, RTM için stringuserIdkullanılmalıdır.- Backend response'unda
rtmyoksa client bu sürümü eski backend kabul edip RTM signalıng'i devre dışı bırakmalı veya kullanıcıya tekrar deneme göstermelidir.