feat: Step 8 - Deepgram token API

Implement serverless-friendly Deepgram token generation.

This provides a secure, stateless way for clients to use Deepgram's
real-time streaming without exposing the main API key:

1. Client requests temporary token from Next.js API
2. Server generates short-lived (60s) token with 'member' scope
3. Client uses token to connect directly to Deepgram WebSocket

This architecture bypasses Vercel's serverless WebSocket limitations
while maintaining security by keeping the main Deepgram API key
server-side only.

Security:
- Main API key never exposed to client
- Temporary tokens expire in 60 seconds
- Minimal 'member' scope permissions

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-11-09 00:14:41 +00:00
parent e43d6493d2
commit d977620c92

View File

@@ -0,0 +1,47 @@
import { NextRequest, NextResponse } from 'next/server';
import { createClient } from '@deepgram/sdk';
/**
* This API route generates a short-lived, temporary API key
* for a client to connect directly to Deepgram's WebSocket.
* This avoids exposing our main API key and bypasses
* serverless WebSocket limitations.
*/
export async function POST(request: NextRequest) {
const deepgramApiKey = process.env.DEEPGRAM_API_KEY;
if (!deepgramApiKey) {
return NextResponse.json(
{ error: 'Deepgram API key not configured' },
{ status: 500 }
);
}
const deepgram = createClient(deepgramApiKey);
try {
// Create a new, temporary key with 'member' permissions
// that expires in 1 minute (60 seconds).
const response = await deepgram.manage.createProjectKey(
process.env.DEEPGRAM_PROJECT_ID || '',
{
comment: 'Temporary key for Ponderants user',
scopes: ['member'],
time_to_live_in_seconds: 60,
}
);
if (!response || !response.key) {
throw new Error('Failed to create temporary key');
}
// Send the temporary key back to the client
return NextResponse.json({ key: response.key });
} catch (error) {
console.error('Error creating Deepgram key:', error);
return NextResponse.json(
{ error: 'Failed to generate voice token' },
{ status: 500 }
);
}
}