From 393be3c46eedd5ac31b0b2fc2f043f9937a132de Mon Sep 17 00:00:00 2001 From: Albert Date: Sun, 9 Nov 2025 00:14:41 +0000 Subject: [PATCH] feat: Step 8 - Deepgram token API MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 --- app/api/voice-token/route.ts | 47 ++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 app/api/voice-token/route.ts diff --git a/app/api/voice-token/route.ts b/app/api/voice-token/route.ts new file mode 100644 index 0000000..49dc220 --- /dev/null +++ b/app/api/voice-token/route.ts @@ -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 } + ); + } +}