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

# Authentication

> Secure your voice agents with authentication and authorization

## Overview

Outspeed provides flexible authentication options to balance ease of development with production security needs.

## Authentication Modes

### Development Mode (No Auth)

Perfect for prototyping and development - no backend required.

1. **Create agent** in the [Outspeed Dashboard](https://dashboard.outspeed.com/agents)
2. **Disable authentication** in agent settings
3. **Use directly** from your client app

```typescript theme={null}
await conversation.startSession({
  agentId: "your-agent-id",
  source: "my-app",
});
```

### Production Mode (Auth Enabled)

Recommended for production apps - requires backend for security.

1. **Enable authentication** in agent settings
2. **Set up backend** to [generate ephemeral keys](#backend-implementation)
3. **Pass ephemeral key** when starting sessions

```typescript theme={null}
const ephemeralKey = await getEphemeralKeyFromServer("your-agent-id");
await conversation.startSession({
  agentId: "your-agent-id",
  source: "my-app",
  ephemeralKey: ephemeralKey,
});
```

## Dashboard Configuration

### Creating an Agent

1. Go to [Outspeed Dashboard](https://dashboard.outspeed.com)
2. Click **Create Agent**
3. Configure your agent:
   * **Name**: Give your agent a name
   * **Voice**: Choose from available voices
4. Once created, you can configure other settings like system instructions, first message, etc. in the dashboard.

### Authentication Settings

In your agent settings, you can:

* **Toggle Authentication**: Enable/disable auth requirements
* **Set Allowed Hostnames**: Restrict which domains can use your agent
* **View Agent ID**: Copy the ID to use in your code

### Hostname Security

Add allowed hostnames to restrict where your agent can be used:

* `example.com` - Allow only this exact domain
* `app.domain.com` - Allow specific subdomain

<Note>We do not support wildcard domains yet.</Note>

<Warning>
  Sessions will only start if the request origin matches your allowlist. Leave empty to allow any origin.
</Warning>

## Backend Implementation

### Simple Agent-Based Auth

For agents created in the dashboard, you only need the agent ID:

<CodeGroup>
  ```javascript Express.js theme={null}
  app.use(express.json());

  app.post("/token", async (req, res) => {
    try {
      const { agentId } = req.body;

      const response = await fetch(`https://api.outspeed.com/v1/realtime/sessions?agent_id=${agentId}`, {
        method: "POST",
        headers: {
          Authorization: `Bearer ${process.env.OUTSPEED_API_KEY}`,
          "Content-Type": "application/json",
        },
      });

      if (!response.ok) {
        const error = await response.text();
        console.error("Failed to generate ephemeral key:", error);
        res.status(response.status).json({ error: "Failed to generate token" });
        return;
      }

      const data = await response.json();
      res.json(data);
    } catch (error) {
      console.error("Failed to generate ephemeral key:", error);
      res.status(500).json({ error: "Internal server error" });
    }
  });
  ```

  ```python FastAPI theme={null}
  import os
  import httpx
  from fastapi import FastAPI, HTTPException

  OUTSPEED_API_KEY = os.getenv("OUTSPEED_API_KEY")
  app = FastAPI()

  @app.post("/token")
  async def create_token(request: dict):
      try:
          agent_id = request.get("agentId")

          async with httpx.AsyncClient() as client:
              response = await client.post(
                  f"https://api.outspeed.com/v1/realtime/sessions?agent_id={agent_id}",
                  headers={
                      "Authorization": f"Bearer {OUTSPEED_API_KEY}",
                      "Content-Type": "application/json",
                  },
              )
              if not response.is_success:
                  print("Error generating ephemeral key:", response.text)
                  raise HTTPException(status_code=response.status_code, detail=response.text)
              return response.json()
      except Exception as e:
          print("Error generating ephemeral key:", e)
          raise HTTPException(status_code=500, detail="Internal server error")
  ```
</CodeGroup>

### Frontend Integration

```typescript theme={null}
const getEphemeralKeyFromServer = async (agentId: string) => {
  const tokenResponse = await fetch("/token", {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({ agentId }),
  });

  const data = await tokenResponse.json();
  if (!tokenResponse.ok) {
    throw new Error("Failed to get ephemeral key");
  }

  return data.client_secret.value;
};

// Usage
const ephemeralKey = await getEphemeralKeyFromServer("your-agent-id");
await conversation.startSession({
  agentId: "your-agent-id",
  source: "my-app",
  ephemeralKey: ephemeralKey,
});
```

## Legacy: Programmatic Configuration

<Note>
  The new dashboard approach is recommended, but you can still configure agents programmatically for advanced use cases.
</Note>

### Backend with Session Config

<CodeGroup>
  ```javascript Express.js theme={null}
  app.use(express.json());

  app.post("/token", async (req, res) => {
    try {
      const response = await fetch("https://api.outspeed.com/v1/realtime/sessions", {
        method: "POST",
        headers: {
          Authorization: `Bearer ${process.env.OUTSPEED_API_KEY}`,
          "Content-Type": "application/json",
        },
        body: JSON.stringify(req.body),
      });

      if (!response.ok) {
        const error = await response.text();
        console.error("failed to generate ephemeral key:", error);
        res.status(response.status).json({ error: "Failed to generate token" });
        return;
      }

      const data = await response.json();
      res.json(data);
    } catch (error) {
      console.error("failed to generate ephemeral key:", error);
      res.status(500).json({ error: "Internal server error" });
    }
  });
  ```

  ```python FastAPI theme={null}
  import os

  import httpx
  from fastapi import FastAPI, HTTPException, Request

  OUTSPEED_API_KEY = os.getenv("OUTSPEED_API_KEY")
  app = FastAPI()


  @app.post("/token")
  async def create_token(request: Request):
      try:
          session_config = await request.json()
          async with httpx.AsyncClient() as client:
              response = await client.post(
                  "https://api.outspeed.com/v1/realtime/sessions",
                  headers={
                      "Authorization": f"Bearer {OUTSPEED_API_KEY}",
                      "Content-Type": "application/json",
                  },
                  json=session_config,
              )
              if not response.is_success:
                  print("error generating ephemeral key:", response.text)
                  raise HTTPException(status_code=response.status_code, detail=response.text)
              return response.json()
      except Exception as e:
          print("error generating ephemeral key:", e)
          raise HTTPException(status_code=500, detail="Internal server error")
  ```
</CodeGroup>

### Frontend with Session Config

```typescript theme={null}
import { type SessionConfig } from "@outspeed/client";

const getEphemeralKeyFromServer = async (config: SessionConfig) => {
  const tokenResponse = await fetch("/token", {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify(config),
  });

  const data = await tokenResponse.json();
  if (!tokenResponse.ok) {
    throw new Error("Failed to get ephemeral key");
  }

  return data.client_secret.value;
};

const sessionConfig: SessionConfig = {
  model: "outspeed-v1",
  instructions: "You are a helpful assistant.",
  voice: "sophie",
  temperature: 0.5,
  turn_detection: {
    type: "semantic_vad",
  },
  first_message: "Hello! How can I help you today?",
};

// Usage
const ephemeralKey = await getEphemeralKeyFromServer(sessionConfig);
await conversation.startSession(ephemeralKey, {
  source: "my-app",
});
```

## Environment Setup

### Required Environment Variables

```bash theme={null}
# Your Outspeed API key from the dashboard
OUTSPEED_API_KEY=your_outspeed_api_key_here
```

### Security Best Practices

<Warning>
  **Never expose your API key in client-side code**. Always generate ephemeral tokens on your backend server.
</Warning>

* **API Keys**: Keep server-side only, never in frontend code
* **Ephemeral Keys**: Short-lived tokens for client authentication
* **Hostname Allowlist**: Restrict origins that can use your agent
* **HTTPS**: Always use HTTPS in production
* **Rate Limiting**: Implement rate limiting on your token endpoint

## When to Use Each Mode

### Development Mode (No Auth)

* ✅ **Prototyping** and development
* ✅ **Internal tools** with trusted users
* ✅ **Quick demos** and experiments
* ❌ **Production apps** with external users

### Production Mode (Auth Enabled)

* ✅ **Production applications**
* ✅ **Public-facing** voice agents
* ✅ **Hostname restrictions** for security

## Summary

1. **Start simple**: Use dashboard agents with auth disabled for development
2. **Add security**: Enable auth and set up backend for production
3. **Restrict access**: Use hostname allowlist for additional security

Both approaches give you full control - choose based on your security and deployment needs.
