Skip to content

Commit e639708

Browse files
authored
Update moq api (#269)
1 parent 3314650 commit e639708

13 files changed

Lines changed: 221 additions & 271 deletions

docs/explanation/moq-with-fishjam.mdx

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -98,42 +98,51 @@ Access to the relay is controlled by **MoQ tokens** — short-lived JWTs that ar
9898
| Publisher token | Write access to a specific path | Streamer |
9999
| Subscriber token | Read access to a path or namespace | Viewer |
100100

101-
A token is attached to the relay URL as a query parameter (`?jwt=<token>`). The relay validates the token and enforces its scope before allowing any media to flow.
101+
A token is attached to the relay URL as a query parameter (`?jwt=<token>`). The relay validates the token and enforces its scope before allowing any media to flow. Both the Sandbox API and the Server SDK hand you the authenticated **connection URL** (the relay URL with the token already embedded), so the client can just take it as is and connect.
102102

103103
Keeping publisher and subscriber tokens separate ensures that a viewer can never accidentally publish to the stream, and a publisher cannot subscribe to paths it does not own.
104104

105-
## Getting Tokens
105+
## Where to get the Connection URL from?
106106

107-
There are two ways to obtain MoQ tokens, depending on where you are in the development lifecycle.
107+
There are two ways to obtain a MoQ connection URL, depending on where you are in the development lifecycle.
108108

109109
### Sandbox API (prototyping)
110110

111-
The **Sandbox API** is a ready-made backend provided by Fishjam for development and prototyping. It issues tokens without requiring you to build your own server, so you can start streaming immediately.
111+
The **Sandbox API** is a ready-made backend provided by Fishjam for development and prototyping. It issues connection URLs without requiring you to build your own server, so you can start streaming immediately.
112112

113-
To get a publisher token, call:
113+
To get a publisher connection URL, call:
114114

115115
```
116116
GET https://fishjam.io/api/v1/connect/{FISHJAM_ID}/room-manager/moq/{PUBLISHER-PATH}/publisher
117117
```
118118

119-
To get a subscriber token, call:
119+
To get a subscriber connection URL, call:
120120

121121
```
122122
GET https://fishjam.io/api/v1/connect/{FISHJAM_ID}/room-manager/moq/{SUBSCRIBER-PATH}/subscriber
123123
```
124124

125+
To get a full-access connection URL — one that can both publish to and subscribe on the path — call:
126+
127+
```
128+
GET https://fishjam.io/api/v1/connect/{FISHJAM_ID}/room-manager/moq/{PATH}/full-access
129+
```
130+
131+
Each returns a JSON object with a `connection_url` field — the relay URL with the JWT embedded as `?jwt=` — alongside the raw `token`.
132+
125133
The Sandbox API is **not intended for production** — it has no authentication and is only available in the Sandbox environment. See [What is the Sandbox API?](./sandbox-api-concept) for more context.
126134

127135
### Fishjam Server SDK (production)
128136

129-
In production, your backend generates tokens using the **Fishjam Server SDK**. This gives you full control over who can publish and who can subscribe.
137+
In production, your backend generates connection URLs using the **Fishjam Server SDK**. This gives you full control over who can publish and who can subscribe.
130138

131-
The SDK's `createMoqToken` method accepts either a `publishPath` or a `subscribePath`:
139+
The SDK's `createMoqAccess` method accepts a `publishPath`, a `subscribePath`, or both, and returns the MoQ access details — a `connection_url` (the relay URL with the JWT embedded) alongside the raw `token`:
132140

133-
- `publishPath` — issues a publisher token scoped to that path.
134-
- `subscribePath` — issues a subscriber token scoped to that path or namespace prefix.
141+
- `publishPath` — returns a publisher connection URL scoped to that path.
142+
- `subscribePath` — returns a subscriber connection URL scoped to that path or namespace prefix.
143+
- both `publishPath` and `subscribePath` — returns a full-access connection URL that can publish and subscribe on those paths.
135144

136-
Your backend then delivers each token to the appropriate client (publisher or viewer), which uses it to connect to the relay.
145+
Your backend then delivers each connection URL to the appropriate client (publisher or viewer), which uses it to connect to the relay.
137146

138147
See the [Web Publishing](../tutorials/moq/web-publishing) and [Web Subscribing](../tutorials/moq/web-subscribing) tutorials (or their [React Native](../tutorials/moq/react-native-publishing) [counterparts](../tutorials/moq/react-native-subscribing)) for working code examples.
139148

docs/tutorials/moq/react-native-publishing.mdx

Lines changed: 16 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -47,12 +47,12 @@ MoQ is a protocol with a well-defined negotiation, so a publisher and a subscrib
4747

4848
If you don't have a backend server set up, you can prototype publishing using the [Sandbox API](../../explanation/sandbox-api-concept).
4949

50-
### Obtaining a publisher token
50+
### Obtaining a publisher connection URL
5151

5252
For more on what the Sandbox API is and its limitations, see [What is the Sandbox API?](../../explanation/sandbox-api-concept).
5353

5454
:::info
55-
To obtain a MoQ token you'll need your Fishjam ID and Sandbox API URL. If you don't have them already, see [Sandbox API URL and Fishjam ID](../../explanation/sandbox-api-concept#sandbox-api-url-and-fishjam-id).
55+
To obtain a MoQ connection URL you'll need your Sandbox API URL. If you don't have it already, see [Sandbox API URL](../../explanation/sandbox-api-concept#sandbox-api-url-and-fishjam-id).
5656
:::
5757

5858
<Tabs groupId="sandbox-token">
@@ -64,17 +64,16 @@ To obtain a MoQ token you'll need your Fishjam ID and Sandbox API URL. If you do
6464
// @noErrors
6565
import { useSandbox } from "@fishjam-cloud/react-native-client";
6666

67-
const FISHJAM_ID = "YOUR_FISHJAM_ID";
6867
const PUBLISHER_PATH = "stream-alice";
6968
const SANDBOX_API_URL = "YOUR_SANDBOX_API_URL";
7069

7170
// Inside a React component:
72-
const { getSandboxMoqPublisherToken } = useSandbox({
71+
const { getSandboxMoqPublisherAccess } = useSandbox({
7372
sandboxApiUrl: SANDBOX_API_URL,
7473
});
7574

76-
// Request a publisher token scoped to the publisher path
77-
const publishToken = await getSandboxMoqPublisherToken(PUBLISHER_PATH);
75+
// Request a publisher connection URL scoped to the publisher path
76+
const { connection_url: publishUrl } = await getSandboxMoqPublisherAccess(PUBLISHER_PATH);
7877
```
7978

8079
</TabItem>
@@ -85,14 +84,13 @@ To obtain a MoQ token you'll need your Fishjam ID and Sandbox API URL. If you do
8584

8685
```ts
8786
// @noErrors
88-
const FISHJAM_ID = "YOUR_FISHJAM_ID";
8987
const PUBLISHER_PATH = "stream-alice";
9088
const SANDBOX_API_URL = "YOUR_SANDBOX_API_URL";
9189

9290
const response = await fetch(
9391
`${SANDBOX_API_URL}/moq/${PUBLISHER_PATH}/publisher`,
9492
);
95-
const { token: publishToken } = await response.json();
93+
const { connection_url: publishUrl } = await response.json();
9694
```
9795

9896
</TabItem>
@@ -102,7 +100,7 @@ To obtain a MoQ token you'll need your Fishjam ID and Sandbox API URL. If you do
102100

103101
`react-native-moq` is hooks-based. You open a session against the relay, capture the camera and microphone, and hand them to a publisher.
104102

105-
Build the relay URL using the publisher token, open the session, and publish the camera + microphone tracks:
103+
Open the session with the publisher connection URL, capture the camera and microphone, and publish the tracks:
106104

107105
```tsx
108106
// @noErrors
@@ -116,16 +114,12 @@ import {
116114
useSession,
117115
} from "react-native-moq";
118116

119-
const FISHJAM_ID = "YOUR_FISHJAM_ID";
120117
const PUBLISHER_PATH = "stream-alice";
121-
const publishToken = ""; // from the step above
122-
123-
// Build the relay URL using the publisher token
124-
const relayUrl = `https://relay.fishjam.io/${FISHJAM_ID}?jwt=${publishToken}`;
118+
const publishUrl = ""; // from the step above
125119

126120
function PublishScreen() {
127-
// Open the MoQ session against the Fishjam relay
128-
const session = useSession(relayUrl, (s) => s.connect());
121+
// Open the MoQ session against the Fishjam relay using the publisher connection URL
122+
const session = useSession(publishUrl, (s) => s.connect());
129123
const camera = useCamera({ position: "front" });
130124
const microphone = useMicrophone();
131125
const publisher = usePublisher(session);
@@ -174,7 +168,7 @@ The session owns the connection to the relay; the publisher reuses it. Because p
174168

175169
The [Quickstart](#quickstart-with-the-sandbox-api) gets you publishing quickly. In production, your backend generates tokens with proper authorization, so you control who can publish.
176170

177-
A **publisher token** grants write access to a specific path. Generate one on your backend and deliver it to the broadcasting client:
171+
A **publisher connection URL** grants write access to a specific path. Generate one on your backend and deliver it to the broadcasting client:
178172

179173
<Tabs groupId="language">
180174
<TabItem value="ts" label="TypeScript">
@@ -193,8 +187,8 @@ A **publisher token** grants write access to a specific path. Generate one on yo
193187

194188
const streamPath = 'stream-alice';
195189

196-
// Generate a token that allows publishing to 'stream-alice'
197-
const { token: publishToken } = await fishjamClient.createMoqToken({
190+
// Generate a connection URL that allows publishing to 'stream-alice'
191+
const { connection_url: publishUrl } = await fishjamClient.createMoqAccess({
198192
publishPath: streamPath,
199193
});
200194
```
@@ -213,14 +207,14 @@ A **publisher token** grants write access to a specific path. Generate one on yo
213207

214208
stream_path = 'stream-alice'
215209

216-
# Generate a token that allows publishing to 'stream-alice'
217-
publish_token = fishjam_client.create_moq_token(publish_path=stream_path)
210+
# Generate a connection URL that allows publishing to 'stream-alice'
211+
publish_url = fishjam_client.create_moq_access(publish_path=stream_path).connection_url
218212
```
219213

220214
</TabItem>
221215
</Tabs>
222216

223-
Deliver this token to the mobile client, then use it to build the relay URL and connect as described in [Connecting and publishing](#connecting-and-publishing).
217+
Deliver this connection URL to the mobile client, then use it to connect as described in [Connecting and publishing](#connecting-and-publishing).
224218

225219
## See also
226220

docs/tutorials/moq/react-native-subscribing.mdx

Lines changed: 27 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -55,12 +55,12 @@ If you don't have a backend server set up, you can prototype subscribing using t
5555
MoQ is a protocol with a well-defined negotiation, so a publisher and a subscriber don't need to use the same client library. A stream published from the browser with [`@moq/publish`](./web-publishing) can be watched with `react-native-moq`, and vice versa.
5656
:::
5757

58-
### Obtaining a subscriber token
58+
### Obtaining a subscriber connection URL
5959

6060
For more on what the Sandbox API is and its limitations, see [What is the Sandbox API?](../../explanation/sandbox-api-concept).
6161

6262
:::info
63-
To obtain a MoQ token you'll need your Fishjam ID and Sandbox API URL. If you don't have them already, see [Sandbox API URL and Fishjam ID](../../explanation/sandbox-api-concept#sandbox-api-url-and-fishjam-id).
63+
To obtain a MoQ connection URL you'll need your Sandbox API URL. If you don't have it already, see [Sandbox API URL](../../explanation/sandbox-api-concept#sandbox-api-url-and-fishjam-id).
6464
:::
6565

6666
<Tabs groupId="sandbox-token">
@@ -72,17 +72,16 @@ To obtain a MoQ token you'll need your Fishjam ID and Sandbox API URL. If you do
7272
// @noErrors
7373
import { useSandbox } from "@fishjam-cloud/react-native-client";
7474

75-
const FISHJAM_ID = "YOUR_FISHJAM_ID";
7675
const SUBSCRIBER_PATH = "stream-alice";
7776
const SANDBOX_API_URL = "YOUR_SANDBOX_API_URL";
7877

7978
// Inside a React component:
80-
const { getSandboxMoqSubscriberToken } = useSandbox({
79+
const { getSandboxMoqSubscriberAccess } = useSandbox({
8180
sandboxApiUrl: SANDBOX_API_URL,
8281
});
8382

84-
// Request a subscriber token scoped to the subscriber path
85-
const subscribeToken = await getSandboxMoqSubscriberToken(SUBSCRIBER_PATH);
83+
// Request a subscriber connection URL scoped to the subscriber path
84+
const { connection_url: subscribeUrl } = await getSandboxMoqSubscriberAccess(SUBSCRIBER_PATH);
8685
```
8786

8887
</TabItem>
@@ -93,14 +92,13 @@ To obtain a MoQ token you'll need your Fishjam ID and Sandbox API URL. If you do
9392

9493
```ts
9594
// @noErrors
96-
const FISHJAM_ID = "YOUR_FISHJAM_ID";
9795
const SUBSCRIBER_PATH = "stream-alice";
9896
const SANDBOX_API_URL = "YOUR_SANDBOX_API_URL";
9997

10098
const response = await fetch(
10199
`${SANDBOX_API_URL}/moq/${SUBSCRIBER_PATH}/subscriber`,
102100
);
103-
const { token: subscribeToken } = await response.json();
101+
const { connection_url: subscribeUrl } = await response.json();
104102
```
105103

106104
</TabItem>
@@ -121,16 +119,12 @@ import {
121119
} from "react-native-moq";
122120
import type { BroadcastInfo } from "react-native-moq";
123121

124-
const FISHJAM_ID = "YOUR_FISHJAM_ID";
125122
const SUBSCRIBER_PATH = "stream-alice";
126-
const subscribeToken = ""; // from the step above
127-
128-
// Build the relay URL using the subscriber token
129-
const relayUrl = `https://relay.fishjam.io/${FISHJAM_ID}?jwt=${subscribeToken}`;
123+
const subscribeUrl = ""; // from the step above
130124

131125
function WatchScreen() {
132-
// Connect to the Fishjam MoQ relay on mount
133-
const session = useSession(relayUrl, (s) => s.connect());
126+
// Connect to the Fishjam MoQ relay on mount using the subscriber connection URL
127+
const session = useSession(subscribeUrl, (s) => s.connect());
134128

135129
// Discover broadcasts under the subscriber path
136130
const broadcasts = useBroadcasts(session, SUBSCRIBER_PATH);
@@ -198,7 +192,7 @@ It exposes imperative `enterFullscreen()` / `exitFullscreen()` methods on its re
198192

199193
The [Quickstart](#quickstart-with-the-sandbox-api) gets you watching quickly. In production, your backend generates tokens with proper authorization, so you control who can subscribe.
200194

201-
A **subscriber token** grants read access to a specific path. Generate one on your backend and deliver it to the viewing client:
195+
A **subscriber connection URL** grants read access to a specific path. Generate one on your backend and deliver it to the viewing client:
202196

203197
<Tabs groupId="language">
204198
<TabItem value="ts" label="TypeScript">
@@ -217,8 +211,8 @@ A **subscriber token** grants read access to a specific path. Generate one on yo
217211

218212
const streamPath = 'stream-alice';
219213

220-
// Generate a token that allows subscribing to 'stream-alice'
221-
const { token: subscribeToken } = await fishjamClient.createMoqToken({
214+
// Generate a connection URL that allows subscribing to 'stream-alice'
215+
const { connection_url: subscribeUrl } = await fishjamClient.createMoqAccess({
222216
subscribePath: streamPath,
223217
});
224218
```
@@ -237,21 +231,21 @@ A **subscriber token** grants read access to a specific path. Generate one on yo
237231

238232
stream_path = 'stream-alice'
239233

240-
# Generate a token that allows subscribing to 'stream-alice'
241-
subscribe_token = fishjam_client.create_moq_token(subscribe_path=stream_path)
234+
# Generate a connection URL that allows subscribing to 'stream-alice'
235+
subscribe_url = fishjam_client.create_moq_access(subscribe_path=stream_path).connection_url
242236
```
243237

244238
</TabItem>
245239
</Tabs>
246240

247-
Deliver this token to the mobile client, then use it to build the relay URL and connect as described in [Connecting and subscribing](#connecting-and-subscribing).
241+
Deliver this connection URL to the mobile client, then use it to connect as described in [Connecting and subscribing](#connecting-and-subscribing).
248242

249243
### Subscribe to a namespace
250244

251245
When multiple publishers join a room, you won't know their exact paths in advance.
252246
Instead of consuming a single path, you can **discover** all broadcasts published under a namespace prefix and subscribe to each one as they appear.
253247

254-
To do this, generate a subscriber token scoped to the room namespace instead of a single stream path.
248+
To do this, generate a subscriber connection URL scoped to the room namespace instead of a single stream path.
255249

256250
<Tabs groupId="language">
257251
<TabItem value="ts" label="TypeScript">
@@ -267,16 +261,16 @@ To do this, generate a subscriber token scoped to the room namespace instead of
267261

268262
const roomName = 'my-room';
269263

270-
const { token: alicePublisherToken } = await fishjamClient.createMoqToken({
264+
const { connection_url: alicePublisherUrl } = await fishjamClient.createMoqAccess({
271265
publishPath: roomName + "/alice",
272266
});
273267

274-
const { token: bobPublisherToken } = await fishjamClient.createMoqToken({
268+
const { connection_url: bobPublisherUrl } = await fishjamClient.createMoqAccess({
275269
publishPath: roomName + "/bob",
276270
});
277271

278272

279-
const { token: namespaceToken } = await fishjamClient.createMoqToken({
273+
const { connection_url: namespaceUrl } = await fishjamClient.createMoqAccess({
280274
subscribePath: roomName,
281275
});
282276
```
@@ -295,21 +289,21 @@ To do this, generate a subscriber token scoped to the room namespace instead of
295289

296290
room_name = 'my-room'
297291

298-
alice_publisher_token = fishjam_client.create_moq_token(
292+
alice_publisher_url = fishjam_client.create_moq_access(
299293
publish_path=room_name + "/alice",
300-
)
294+
).connection_url
301295

302-
bob_publisher_token = fishjam_client.create_moq_token(
296+
bob_publisher_url = fishjam_client.create_moq_access(
303297
publish_path=room_name + "/bob",
304-
)
298+
).connection_url
305299

306-
namespace_token = fishjam_client.create_moq_token(subscribe_path=room_name)
300+
namespace_url = fishjam_client.create_moq_access(subscribe_path=room_name).connection_url
307301
```
308302

309303
</TabItem>
310304
</Tabs>
311305

312-
On the client, pass the namespace token's relay URL to `useSession`, then call `useBroadcasts(session, roomName)` with the room prefix. It returns a reactive `BroadcastInfo[]` that re-renders every time a publisher joins or leaves — no manual diffing of an announce set. Map over it to mount a player per broadcast:
306+
On the client, pass the namespace connection URL to `useSession`, then call `useBroadcasts(session, roomName)` with the room prefix. It returns a reactive `BroadcastInfo[]` that re-renders every time a publisher joins or leaves — no manual diffing of an announce set. Map over it to mount a player per broadcast:
313307

314308
```tsx
315309
// @noErrors
@@ -321,14 +315,11 @@ import {
321315
} from "react-native-moq";
322316
import type { BroadcastInfo } from "react-native-moq";
323317

324-
const FISHJAM_ID = "YOUR_FISHJAM_ID";
325318
const ROOM_NAME = "my-room";
326-
const namespaceToken = "token";
327-
328-
const relayUrl = `https://relay.fishjam.io/${FISHJAM_ID}?jwt=${namespaceToken}`;
319+
const namespaceUrl = "";
329320

330321
function RoomGrid() {
331-
const session = useSession(relayUrl, (s) => s.connect());
322+
const session = useSession(namespaceUrl, (s) => s.connect());
332323

333324
// Every broadcast published under the 'my-room' prefix, kept live
334325
const broadcasts = useBroadcasts(session, ROOM_NAME);

0 commit comments

Comments
 (0)