> ## Documentation Index
> Fetch the complete documentation index at: https://docs.livepeer.org/llms.txt
> Use this file to discover all available pages before exploring further.

# Access control with JWTs

> Gate playback using signed JWTs so only viewers with a valid token can watch.

With **JWT** access control, you mark a stream or asset as gated. Viewers must send a **JWT** signed with a Studio **signing key**. You issue JWTs from your backend after validating the user.

## 1. Create a signing key

In the dashboard or via the [Signing Key API](https://livepeer.studio/docs/api-reference/signing-key/create), create a signing key. Store the **private key** in your backend (env) and use the **public key** in Studio for verification.

## 2. Create gated content

Set `playbackPolicy.type` to `"jwt"` when creating the stream or asset:

```ts icon="terminal" theme={"theme":{"light":"github-light","dark":"dark-plus"}}
await livepeer.stream.create({ name: "Gated", playbackPolicy: { type: "jwt" } });
await livepeer.asset.create({ name: "Gated", playbackPolicy: { type: "jwt" } });
```

## 3. Sign and return a JWT from your API

In a backend route (e.g. `/api/sign-jwt`), validate the user, then sign a JWT with the private key. Include `playbackId`, expiration, and any custom claims. Return the token to the client. Use `@livepeer/core/crypto` `signAccessJwt` or any JWT library with the same claims Livepeer expects (see [Livepeer Studio docs](https://livepeer.studio/docs)).

## 4. Pass the JWT to the Player

```tsx icon="terminal" theme={"theme":{"light":"github-light","dark":"dark-plus"}}
<Player.Root src={src} jwt={jwt}>
  <Player.Container><Player.Video /></Player.Container>
</Player.Root>
```

**Custom player:** Send the JWT in the `Livepeer-Jwt` header for WebRTC/HLS, or as query param `jwt` on the playback URL.
