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

# SDK setup

Use these instructions to install, authenticate and instantiate the Spaces SDK.

## Authenticate

<Aside data-type="important">
  Client-side applications must use [token authentication](/docs/auth/token). API keys should never be exposed in client-side code because they don't expire and cannot be scoped to specific users.
</Aside>

Spaces requires an authenticated client with a `clientId` to identify users. The recommended approach is:

1. **Client-side apps** (browsers, mobile apps): Use [JWT authentication](/docs/auth/token/jwt) with `authCallback` to fetch JWTs from your server
2. **Server-side apps** (Node.js, Python, etc.): Use your API key directly

[Sign up](https://ably.com/sign-up) to Ably to create an API key in the [dashboard](https://ably.com/dashboard) or use the [Control API](/docs/platform/account/control-api) to create an API programmatically. Your server will use this key to issue tokens to clients.

API keys and tokens have a set of capabilities assigned to them that specify which operations, such as `subscribe` or `publish` can be performed on which resources. To use the Spaces SDK, the API key requires the following [capabilities](/docs/auth/capabilities):

* Publish
* Subscribe
* Presence
* History

For space-scoped capabilities and channel architecture details, see [Spaces authentication](/docs/spaces/authentication).

### Client identification

Every Spaces client must have a `clientId` - this is a **hard requirement**. The Spaces SDK uses the `clientId` to identify users in the avatar stack, track their locations, display their cursors, and manage component locking.

Your auth server sets the `clientId` when creating tokens. This ensures users can't impersonate each other - the identity is controlled server-side, not by the client.

If you try to connect without a `clientId`, the connection will fail.

## Install

<Aside data-type="note">
  The JavaScript SDK can be used with React. We also provide a dedicated [React Hooks package.](/docs/spaces/react-hooks)
</Aside>

The Spaces SDK is built on top of the Ably JavaScript SDK and uses it to establish a connection with Ably. Therefore the Ably JavaScript SDK is installed alongside the Spaces SDK.

Both SDKs are available as [NPM modules](#npm) and via [CDN.](#cdn)

### Using NPM

Install the Ably JavaScript SDK and the Spaces SDK:

<Code>
  ```shell theme={null}
  npm install @ably/spaces
  ```
</Code>

Import the SDKs into your project:

<Code>
  ```javascript theme={null}
  import Spaces from '@ably/spaces';
  import { Realtime } from 'ably';
  ```
</Code>

### Using a CDN

Reference the Ably JavaScript SDK and the Spaces SDK within the `<head>` of your HTML file:

<Code>
  ```javascript theme={null}
  <script src="https://cdn.ably.com/lib/ably.min-2.js"></script>
  <script src="https://cdn.ably.com/spaces/0.4/iife/index.bundle.js"></script>
  ```
</Code>

## Instantiate

Authentication is configured on the Ably JavaScript SDK client, which the Spaces client wraps. The Spaces SDK itself doesn't handle authentication directly - it uses the authenticated connection from the underlying Ably client.

Instantiate a realtime client using the Ably JavaScript SDK and pass the generated client into the Spaces constructor.

### Client-side authentication (recommended)

Use token authentication for browsers and mobile apps. Your auth server endpoint validates the user and returns an Ably token with the appropriate `clientId`:

<Code>
  ```javascript theme={null}
  // Client-side: Token authentication (recommended for browsers)

  // If installing via NPM
  const client = new Realtime({
    authCallback: async (tokenParams, callback) => {
      try {
        const response = await fetch('/api/ably-token');
        const token = await response.text();
        callback(null, token);
      } catch (error) {
        callback(error, null);
      }
    },
  });
  const spaces = new Spaces(client);

  // If installing via CDN
  const client = new Ably.Realtime({
    authCallback: async (tokenParams, callback) => {
      try {
        const response = await fetch('/api/ably-token');
        const token = await response.text();
        callback(null, token);
      } catch (error) {
        callback(error, null);
      }
    },
  });
  const spaces = new Spaces(client);
  ```
</Code>

Your auth server endpoint (`/api/ably-token`) should authenticate the user and return a token with the user's `clientId`. See the [token authentication](/docs/auth/token) documentation for server implementation examples.

### Server-side authentication

For server-side applications or local development, you can use an API key directly:

<Code>
  ```javascript theme={null}
  // Server-side only: API key authentication
  // WARNING: Never use this in client-side code (browsers, mobile apps)
  const client = new Realtime({
    key: process.env.ABLY_API_KEY,
    clientId: 'server-process-1'
  });
  const spaces = new Spaces(client);
  ```
</Code>

A [`ClientOptions`](/docs/api/realtime-sdk#client-options) object may be passed to the Ably JavaScript SDK to further customize the connection. When using token authentication, the `clientId` is set by your auth server. When using API key authentication server-side, you must provide a `clientId` so that the client is [identified](/docs/auth/identified-clients).

### Using Ably JWT (alternative)

If you have existing JWT-based authentication infrastructure (Auth0, Firebase, Cognito, or custom), you can create Ably JWTs directly without using the Ably SDK on your server:

#### Server (no Ably SDK required)

<Code>
  ```javascript theme={null}
  import jwt from 'jsonwebtoken';

  const [keyName, keySecret] = process.env.ABLY_API_KEY.split(':');

  app.get('/api/ably-jwt', async (req, res) => {
    // Your existing auth middleware validates the user
    const userId = req.user.id;

    const ablyJwt = jwt.sign(
      {
        'x-ably-capability': JSON.stringify({
          '*': ['publish', 'subscribe', 'presence', 'history'],
        }),
        'x-ably-clientId': userId,
      },
      keySecret,
      { algorithm: 'HS256', keyid: keyName, expiresIn: '1h' }
    );

    res.send(ablyJwt);
  });
  ```
</Code>

#### Client

<Code>
  ```javascript theme={null}
  const client = new Realtime({
    authCallback: async (tokenParams, callback) => {
      try {
        const response = await fetch('/api/ably-jwt', {
          headers: { 'Authorization': `Bearer ${yourAppJwt}` },
        });
        const jwt = await response.text();
        callback(null, jwt);
      } catch (error) {
        callback(error, null);
      }
    },
  });
  const spaces = new Spaces(client);
  ```
</Code>

**Why choose JWT for Spaces?**

* No Ably SDK required on your server
* Integrates with existing Auth0/Firebase/Cognito flows
* Supports [channel-scoped claims](/docs/auth/capabilities#custom-restrictions) for user metadata
* Eliminates client round-trip to Ably

See [Token authentication](/docs/auth/token#choosing) for detailed guidance on when to use JWT vs Ably Tokens.

<Aside data-type="note">
  Only the promises version of the Ably JavaScript is supported when using Spaces, not the callback version.
</Aside>

## Client connections

A Spaces client exposes the underlying [connection](/docs/connect) to Ably that is established via the Ably JavaScript SDK. This means that Spaces clients benefit from the same functionality available in the Ably JavaScript SDK, such as automatic transport selection and [connection state recovery](/docs/connect/states) in the event of brief disconnections.

Connections transition through multiple states throughout their lifecycle. Whilst these transitions are handled by the Ably SDK, there are certain cases where you may need to observe and handle them within your application. Ably SDKs enable these transitions to be observed and triggered using methods available on the `connection` object. The Spaces SDK exposes the underlying connection with `spaces.connection`, which is a reference to [`client.connection`](/docs/api/realtime-sdk/connection) in the Ably JavaScript SDK.
