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

# Sessions

> Managing sessions and authentication in Uplink

Sessions are the foundation of Uplink's security and connection model. Understanding how to create, manage, and secure sessions is essential for production use.

## What is a session?

A **session** is an authenticated connection that allows your JavaScript code to communicate with mobile devices. Sessions are created programmatically using your project API key and enable secure, real-time bidirectional communication.

```typescript theme={null}
const session = await uplink.session('<project-api-key>', {
  include: { ecdsa: true, ecdh: true }
})
const client = await uplink.client.fromSession(session)
```

## Creating sessions

Sessions are created programmatically in your code using your project API key. The session is automatically scoped to the project the API key belongs to.

<Steps>
  <Step title="Get your API key">
    In Uplink Console, navigate to **Settings** → **API Keys** to find your project API key. Keep it secure.
  </Step>

  <Step title="Create a session in code">
    Use the `uplink.session()` method to create a session with your API key:

    ```typescript theme={null}
    const session = await uplink.session('<project-api-key>', {
      include: { ecdsa: true, ecdh: true }
    })
    ```
  </Step>

  <Step title="Connect a client to the session">
    Create a client from your session to interact with connected devices:

    ```typescript theme={null}
    const client = await uplink.client.fromSession(session)
    ```
  </Step>

  <Step title="Deliver the session to your device">
    The `session` object exposes two URLs for connecting a device. Use the one that matches your integration:

    <Tabs>
      <Tab title="Connect app">
        Display `session.qrUrl` as a QR code in your UI. When your user scans it, the Uplink Connect app opens and joins the session automatically.

        ```typescript theme={null}
        import QRCode from 'qrcode'

        const qrCodeImage = await QRCode.toDataURL(session.qrUrl)
        // Render qrCodeImage in your UI
        ```
      </Tab>

      <Tab title="Native SDK">
        Deliver `session.sessionUrl` to your app through your own channel (push notification, deep link, API response, etc.), then pass it to the native SDK's `worker.connect` method.

        ```typescript theme={null}
        const sessionUrl = session.sessionUrl
        // Deliver sessionUrl to your iOS or Android app
        ```

        See the [iOS SDK](/api-reference/ios) and [Android SDK](/api-reference/android) guides for how the app side consumes the URL.
      </Tab>
    </Tabs>
  </Step>
</Steps>

## API keys and session security

Sessions are authenticated using your project API key, which provides:

* **Project identity**: Each API key belongs to exactly one project — sessions created with it are scoped to that project automatically.
* **Secure communication**: Encrypted connections between your code and devices
* **Access control**: Manage permissions through Console settings

### Token security best practices

<AccordionGroup>
  <Accordion title="Keep API keys secret" icon="lock">
    Treat API keys like passwords. Never commit them to source control or expose them in client-side code.

    ```typescript theme={null}
    // ✓ Good: Use environment variables
    const session = await uplink.session(process.env.UPLINK_API_KEY, {
      include: { ecdsa: true, ecdh: true }
    })

    // ✗ Bad: Hardcoded credentials
    const session = await uplink.session('sk_live_abc123...', {
      include: { ecdsa: true, ecdh: true }
    })
    ```
  </Accordion>

  <Accordion title="Manage session lifecycle" icon="clock">
    Create and destroy sessions as needed for your use case. For automated testing, create a new session for each test run and close it when complete.

    ```typescript theme={null}
    // Create session for a test
    const session = await uplink.session(process.env.UPLINK_API_KEY, {
      include: { ecdsa: true, ecdh: true }
    })
    const client = await uplink.client.fromSession(session)

    // Run tests...

    // Always clean up
    await client.close()
    ```
  </Accordion>

  <Accordion title="Use project-specific keys" icon="shield">
    Use separate API keys (and projects) to isolate different environments or use cases. This helps organize your automations and manage access control.
  </Accordion>

  <Accordion title="Rotate API keys regularly" icon="rotate">
    Regularly rotate API keys, especially after team member changes or security incidents. You can manage keys in the Uplink Console.
  </Accordion>
</AccordionGroup>

## Session lifecycle

### Connection

When you connect to a session, the client establishes a WebSocket connection to the Uplink relay server:

```typescript theme={null}
const session = await uplink.session('<project-api-key>', {
  include: { ecdsa: true, ecdh: true }
})
const client = await uplink.client.fromSession(session)
console.log('Connected to session')

// The client is now ready to interact with devices
```

### Active session

During an active session:

* Devices can connect and disconnect
* Browsers can be launched and managed
* Commands are sent in real-time
* Events are emitted for device state changes

```typescript theme={null}
client.on('worker-connected', (device) => {
  console.log('Device joined session:', device.address)
})

client.on('worker-disconnected', (device) => {
  console.log('Device left session:', device.address)
})
```

### Closing a session

Always close the client when you're done to properly clean up resources:

```typescript theme={null}
// Clean up in order: pages, browsers, then client
await page.close()
await browser.close()
await client.close()
```

### Session expiration

Sessions end when:

* The connection is closed by the client (`client.close()`)
* The session is terminated in the Console
* The API key used to create the session is revoked
* Network connectivity is lost

<Warning>
  When a session expires, all connected devices are disconnected and browsers are closed. Plan for graceful handling of session expiration in long-running automations.
</Warning>

## Multi-session patterns

### Load distribution

For high-volume automation, distribute load across multiple sessions:

```typescript theme={null}
const sessions = await Promise.all([
  createAndConnectSession('session-1'),
  createAndConnectSession('session-2'),
  createAndConnectSession('session-3')
])

// Round-robin device allocation
const device = sessions[nextIndex++ % sessions.length]
```

## Next steps

<CardGroup cols={2}>
  <Card title="Device management" icon="mobile" href="/fundamentals/device-management">
    Learn how to manage devices in sessions
  </Card>

  <Card title="Client API" icon="plug" href="/api-reference/client">
    Explore the Client API reference
  </Card>
</CardGroup>
