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.
- Create agent in the Outspeed Dashboard
- Disable authentication in agent settings
- Use directly from your client app
await conversation.startSession({
agentId: "your-agent-id",
source: "my-app",
});
Production Mode (Auth Enabled)
Recommended for production apps - requires backend for security.
- Enable authentication in agent settings
- Set up backend to generate ephemeral keys
- Pass ephemeral key when starting sessions
const ephemeralKey = await getEphemeralKeyFromServer("your-agent-id");
await conversation.startSession({
agentId: "your-agent-id",
source: "my-app",
ephemeralKey: ephemeralKey,
});
Dashboard Configuration
Creating an Agent
- Go to Outspeed Dashboard
- Click Create Agent
- Configure your agent:
- Name: Give your agent a name
- Voice: Choose from available voices
- 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
We do not support wildcard domains yet.
Sessions will only start if the request origin matches your allowlist. Leave empty to allow any origin.
Backend Implementation
Simple Agent-Based Auth
For agents created in the dashboard, you only need the agent ID:
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" });
}
});
Frontend Integration
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
The new dashboard approach is recommended, but you can still configure agents programmatically for advanced use cases.
Backend with Session Config
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" });
}
});
Frontend with Session Config
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
# Your Outspeed API key from the dashboard
OUTSPEED_API_KEY=your_outspeed_api_key_here
Security Best Practices
Never expose your API key in client-side code. Always generate ephemeral tokens on your backend server.
- 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
- Start simple: Use dashboard agents with auth disabled for development
- Add security: Enable auth and set up backend for production
- Restrict access: Use hostname allowlist for additional security
Both approaches give you full control - choose based on your security and deployment needs.