Agent skill
assemblyai-webhooks-events
Implement AssemblyAI webhook handling for transcription completion events. Use when setting up webhook endpoints, handling transcription callbacks, or processing async transcription results via webhooks. Trigger with phrases like "assemblyai webhook", "assemblyai events", "assemblyai transcription callback", "handle assemblyai webhook".
Install this agent skill to your Project
npx add-skill https://github.com/jeremylongshore/claude-code-plugins-plus-skills/tree/main/plugins/saas-packs/assemblyai-pack/skills/assemblyai-webhooks-events
SKILL.md
AssemblyAI Webhooks & Events
Overview
Handle AssemblyAI webhooks for transcription completion. When you submit a transcript with webhook_url, AssemblyAI sends a POST request to your URL when the transcript is completed or fails. One webhook per transcript — no complex event routing needed.
Prerequisites
- HTTPS endpoint accessible from the internet
assemblyaipackage installed- API key configured
How AssemblyAI Webhooks Work
- You submit a transcription with
webhook_urlparameter - AssemblyAI processes the audio asynchronously
- When done (completed or error), AssemblyAI sends a POST to your URL
- Your endpoint receives transcript ID and status, then fetches the full transcript
Key difference from other APIs: AssemblyAI webhooks are per-transcript (set at submission time), not a global webhook registration. There are no event types to subscribe to — you get one callback per transcript.
Instructions
Step 1: Submit Transcription with Webhook
import { AssemblyAI } from 'assemblyai';
const client = new AssemblyAI({
apiKey: process.env.ASSEMBLYAI_API_KEY!,
});
// submit() queues the job and returns immediately (doesn't poll)
const transcript = await client.transcripts.submit({
audio: 'https://example.com/meeting-recording.mp3',
webhook_url: 'https://your-app.com/webhooks/assemblyai',
// Optional: auth header for webhook verification
webhook_auth_header_name: 'X-Webhook-Secret',
webhook_auth_header_value: process.env.ASSEMBLYAI_WEBHOOK_SECRET!,
// Enable features — results will be available when webhook fires
speaker_labels: true,
sentiment_analysis: true,
auto_highlights: true,
});
console.log('Submitted:', transcript.id);
// Returns immediately, webhook fires when processing completes
Step 2: Webhook Endpoint (Express.js)
import express from 'express';
import { AssemblyAI, type Transcript } from 'assemblyai';
const app = express();
const client = new AssemblyAI({
apiKey: process.env.ASSEMBLYAI_API_KEY!,
});
app.post('/webhooks/assemblyai', express.json(), async (req, res) => {
// Step 1: Verify authenticity via custom auth header
const secret = req.headers['x-webhook-secret'];
if (secret !== process.env.ASSEMBLYAI_WEBHOOK_SECRET) {
console.warn('Webhook auth failed');
return res.status(401).json({ error: 'Unauthorized' });
}
// Step 2: Extract payload
const { transcript_id, status } = req.body;
console.log(`Webhook received: ${transcript_id} — ${status}`);
// Step 3: Respond quickly (within 10 seconds)
res.status(200).json({ received: true });
// Step 4: Process asynchronously
try {
if (status === 'completed') {
const transcript = await client.transcripts.get(transcript_id);
await processCompletedTranscript(transcript);
} else if (status === 'error') {
await handleFailedTranscript(transcript_id, req.body.error);
}
} catch (error) {
console.error('Webhook processing error:', error);
}
});
async function processCompletedTranscript(transcript: Transcript) {
console.log(`Processing transcript ${transcript.id}:`);
console.log(` Text: ${transcript.text?.length} chars`);
console.log(` Duration: ${transcript.audio_duration}s`);
console.log(` Speakers: ${transcript.utterances?.length ?? 0} utterances`);
// Store in database, notify user, trigger LeMUR analysis, etc.
// Example: Run LeMUR summarization after transcription completes
if (transcript.text && transcript.text.length > 100) {
const { response } = await client.lemur.summary({
transcript_ids: [transcript.id],
answer_format: 'bullet points',
});
console.log('Auto-summary:', response);
}
}
async function handleFailedTranscript(transcriptId: string, error?: string) {
console.error(`Transcript ${transcriptId} failed: ${error}`);
// Alert ops team, retry with different settings, etc.
}
app.listen(3000, () => console.log('Listening on :3000'));
Step 3: Webhook Endpoint (Next.js App Router)
// app/api/webhooks/assemblyai/route.ts
import { AssemblyAI } from 'assemblyai';
import { NextRequest, NextResponse } from 'next/server';
const client = new AssemblyAI({
apiKey: process.env.ASSEMBLYAI_API_KEY!,
});
export async function POST(req: NextRequest) {
const secret = req.headers.get('x-webhook-secret');
if (secret !== process.env.ASSEMBLYAI_WEBHOOK_SECRET) {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
}
const body = await req.json();
const { transcript_id, status } = body;
if (status === 'completed') {
const transcript = await client.transcripts.get(transcript_id);
// Process transcript...
console.log(`Completed: ${transcript_id}, ${transcript.text?.length} chars`);
}
return NextResponse.json({ received: true });
}
Step 4: Idempotent Processing
// Prevent duplicate processing if webhook is retried
const processedTranscripts = new Set<string>();
// In production, use Redis or a database instead of in-memory Set
async function idempotentProcess(transcriptId: string, handler: () => Promise<void>) {
if (processedTranscripts.has(transcriptId)) {
console.log(`Already processed: ${transcriptId}`);
return;
}
await handler();
processedTranscripts.add(transcriptId);
}
// Usage in webhook handler:
await idempotentProcess(transcript_id, async () => {
const transcript = await client.transcripts.get(transcript_id);
await processCompletedTranscript(transcript);
});
Step 5: Testing Webhooks Locally
# Option 1: ngrok
ngrok http 3000
# Use the HTTPS URL as your webhook_url
# Option 2: Simulate webhook manually
curl -X POST http://localhost:3000/webhooks/assemblyai \
-H "Content-Type: application/json" \
-H "X-Webhook-Secret: your-secret" \
-d '{
"transcript_id": "test-id-123",
"status": "completed"
}'
Webhook Payload Reference
AssemblyAI sends a POST with this JSON body:
{
"transcript_id": "6wij2z3g66-...",
"status": "completed"
}
For errors:
{
"transcript_id": "6wij2z3g66-...",
"status": "error",
"error": "Download error: unable to download audio from URL"
}
If redact_pii_audio was enabled, a second webhook fires when redacted audio is ready.
Output
- Webhook endpoint that receives transcription completion events
- Auth header verification for secure webhook handling
- Idempotent processing to handle retries
- LeMUR auto-analysis triggered on completion
Error Handling
| Issue | Cause | Solution |
|---|---|---|
| Webhook not received | URL not accessible from internet | Verify HTTPS URL, check firewall |
| 401 on webhook | Wrong auth header value | Match webhook_auth_header_value from submission |
| Duplicate processing | Webhook retried after timeout | Implement idempotency (check transcript_id) |
| Webhook timeout | Processing > 10 seconds | Return 200 immediately, process async |
| Missing transcript data | Fetching too early | Fetch with client.transcripts.get() after webhook |
Resources
Next Steps
For performance optimization, see assemblyai-performance-tuning.
Recommended Agent Skills
Expand your agent's capabilities with these related and highly-rated skills.
dockerfile-generator
Dockerfile Generator - Auto-activating skill for DevOps Basics. Triggers on: dockerfile generator, dockerfile generator Part of the DevOps Basics skill category.
branch-naming-helper
Branch Naming Helper - Auto-activating skill for DevOps Basics. Triggers on: branch naming helper, branch naming helper Part of the DevOps Basics skill category.
readme-generator
Readme Generator - Auto-activating skill for DevOps Basics. Triggers on: readme generator, readme generator Part of the DevOps Basics skill category.
makefile-generator
Makefile Generator - Auto-activating skill for DevOps Basics. Triggers on: makefile generator, makefile generator Part of the DevOps Basics skill category.
gitignore-generator
Gitignore Generator - Auto-activating skill for DevOps Basics. Triggers on: gitignore generator, gitignore generator Part of the DevOps Basics skill category.
pre-commit-hook-setup
Pre Commit Hook Setup - Auto-activating skill for DevOps Basics. Triggers on: pre commit hook setup, pre commit hook setup Part of the DevOps Basics skill category.
Didn't find tool you were looking for?