Anam uses a two-tier authentication system to keep your API keys secure while enabling real-time client connections.

Tier 1: API Key

Your API key is used to authenticate your requests to the Anam API. It is a secret key that is used to sign your requests and is stored on your server.

Never expose your API key on the client side. It should only exist in your server environment.

Getting Your API Key

See the API key page for details on how to get your API key from the Anam Lab.

Tier 2: Session Tokens

Session tokens are temporary credentials that allow your client applications to connect directly to Anam’s streaming infrastructure while keeping your API keys secure.

How Session Tokens Work

1

Token Request

Your server requests a session token from Anam using your API key and persona configuration

2

Token Generation

Anam generates a temporary token tied to your specific persona configuration

3

Client Connection

Your client uses the session token with the Anam SDK to establish a direct WebRTC connection

4

Real-time Communication

Once connected, the client can send messages and receive video/audio streams directly

Basic Token Creation

Below is a basic express server example that exposes a single endpoint which a client application can use to create a session token.

server.js
const express = require('express');
const app = express();

app.post('/api/session-token', async (req, res) => {
  try {
    const response = await fetch("https://api.anam.ai/v1/auth/session-token", {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
        Authorization: `Bearer ${process.env.ANAM_API_KEY}`,
      },
      body: JSON.stringify({
        personaConfig: {
          name: "Cara",
          avatarId: "30fa96d0-26c4-4e55-94a0-517025942e18",
          voiceId: "6bfbe25a-979d-40f3-a92b-5394170af54b",
          brainType: "ANAM_GPT_4O_MINI_V1",
          systemPrompt: "You are a helpful assistant.",
        },
      }),
    });
    
    const { sessionToken } = await response.json();
    res.json({ sessionToken });
  } catch (error) {
    res.status(500).json({ error: 'Failed to create session' });
  }
});

Advanced Token Creation

Instead of using the same persona configuration for all users, you can utilise context to create different persona configurations for different situations.

Pattern 1: User-based Personalization

For applications with different user types or preferences:

app.post('/api/session-token', authenticateUser, async (req, res) => {
  const user = req.user;
  
  const personaConfig = {
    name: `Persona for user: ${user.id}`,
    avatarId: user.preferredAvatar || defaultAvatarId,
    voiceId: user.preferredVoice || defaultVoiceId,
    brainType: user.preferredBrainType || "ANAM_GPT_4O_MINI_V1",
    systemPrompt: buildPersonalizedPrompt(user),
  };
  
  const sessionToken = await fetchAnamSessionToken(personaConfig);
  res.json({ sessionToken });
});

Pattern 2: Context-aware Sessions

For applications where the persona changes based on context:

app.post('/api/session-token', authenticateUser, async (req, res) => {
  const { context, metadata } = req.body;
  
  let personaConfig;
  
  switch (context) {
    case 'customer-support':
      personaConfig = buildSupportPersona(metadata);
      break;
    case 'sales':
      personaConfig = buildSalesPersona(metadata);
      break;
    case 'training':
      personaConfig = buildTrainingPersona(metadata);
      break;
    default:
      personaConfig = defaultPersonaConfig;
  }
  
  const sessionToken = await fetchAnamSessionToken(personaConfig);
  res.json({ sessionToken });
});

Error Handling

Common authentication errors and how to handle them:

app.post('/api/session-token', async (req, res) => {
  try {
    const response = await fetch("https://api.anam.ai/v1/auth/session-token", {
      // ... config
    });
    
    if (!response.ok) {
      const errorData = await response.json();
      
      switch (response.status) {
        case 401:
          console.error('Invalid API key');
          return res.status(500).json({ error: 'Authentication failed' });
        case 400:
          console.error('Invalid persona config:', errorData);
          return res.status(400).json({ error: 'Invalid configuration' });
        default:
          console.error('Unexpected error:', errorData);
          return res.status(500).json({ error: 'Service unavailable' });
      }
    }
    
    const { sessionToken } = await response.json();
    res.json({ sessionToken });
  } catch (error) {
    console.error('Network error:', error);
    res.status(500).json({ error: 'Network error' });
  }
});

Environment Setup

Store your API key securely:

ANAM_API_KEY=your-api-key-here
NODE_ENV=production

Next Steps