deepgram-webhooks
Receive and verify Deepgram webhooks (callbacks). Use when setting up Deepgram webhook handlers, processing transcription callbacks, or handling asynchronous transcription results.
Packaged view
This page reorganizes the original catalog entry around fit, installability, and workflow context first. The original raw source lives below.
Install command
npx @skill-hub/cli install hookdeck-webhook-skills-deepgram-webhooks
Repository
Skill path: skills/deepgram-webhooks
Receive and verify Deepgram webhooks (callbacks). Use when setting up Deepgram webhook handlers, processing transcription callbacks, or handling asynchronous transcription results.
Open repositoryBest for
Primary workflow: Ship Full Stack.
Technical facets: Full Stack, Integration.
Target audience: everyone.
License: MIT.
Original source
Catalog source: SkillHub Club.
Repository owner: hookdeck.
This is still a mirrored public skill entry. Review the repository before installing into production workflows.
What it helps with
- Install deepgram-webhooks into Claude Code, Codex CLI, Gemini CLI, or OpenCode workflows
- Review https://github.com/hookdeck/webhook-skills before adding deepgram-webhooks to shared team environments
- Use deepgram-webhooks for development workflows
Works across
Favorites: 0.
Sub-skills: 0.
Aggregator: No.
Original source / Raw SKILL.md
---
name: deepgram-webhooks
description: >
Receive and verify Deepgram webhooks (callbacks). Use when setting up Deepgram webhook
handlers, processing transcription callbacks, or handling asynchronous transcription results.
license: MIT
metadata:
author: hookdeck
version: "0.1.0"
repository: https://github.com/hookdeck/webhook-skills
---
# Deepgram Webhooks
## When to Use This Skill
- Setting up Deepgram callback handlers for transcription results
- Processing asynchronous transcription results from Deepgram
- Implementing webhook authentication for Deepgram callbacks
- Handling transcription completion events
## Essential Code
Deepgram webhooks (callbacks) are used to receive transcription results asynchronously. When you provide a callback URL in your transcription request, Deepgram immediately responds with a `request_id` and sends the transcription results to your callback URL when processing is complete.
### Basic Webhook Handler
```javascript
// Express.js example
app.post('/webhooks/deepgram', express.raw({ type: 'application/json' }), (req, res) => {
// Verify webhook authenticity using dg-token header
const dgToken = req.headers['dg-token'];
if (!dgToken) {
return res.status(401).send('Missing dg-token header');
}
// Verify the token matches your expected API Key Identifier
// The dg-token contains the API Key Identifier used in the original request
if (dgToken !== process.env.DEEPGRAM_API_KEY_ID) {
return res.status(403).send('Invalid dg-token');
}
// Parse the transcription result
const transcriptionResult = JSON.parse(req.body.toString());
// Process the transcription
console.log('Received transcription:', transcriptionResult);
// Return success to prevent retries
res.status(200).send('OK');
});
```
### Authentication Methods
Deepgram supports two authentication methods for webhooks:
1. **dg-token Header**: Automatically included, contains the API Key Identifier
2. **Basic Auth**: Embed credentials in the callback URL
```javascript
// Using dg-token header (recommended)
const verifyDgToken = (req, res, next) => {
const dgToken = req.headers['dg-token'];
if (!dgToken || dgToken !== process.env.DEEPGRAM_API_KEY_ID) {
return res.status(403).send('Invalid authentication');
}
next();
};
// Basic Auth in callback URL
// https://username:[email protected]/webhooks/deepgram
```
### Making a Request with Callback
```bash
curl \
--request POST \
--header 'Authorization: Token YOUR_DEEPGRAM_API_KEY' \
--header 'Content-Type: audio/wav' \
--data-binary @audio.wav \
--url 'https://api.deepgram.com/v1/listen?callback=https://your-domain.com/webhooks/deepgram'
```
## Common Event Types
Deepgram sends transcription results as webhook payloads. The structure varies based on the features enabled in your request:
| Field | Description | Always Present |
|-------|-------------|----------------|
| `request_id` | Unique identifier for the transcription request | Yes |
| `created` | Timestamp when transcription was created | Yes |
| `duration` | Length of the audio in seconds | Yes |
| `channels` | Number of audio channels | Yes |
| `results` | Transcription results by channel | Yes |
| `results.channels[].alternatives` | Transcription alternatives | Yes |
| `results.channels[].alternatives[].transcript` | The transcribed text | Yes |
| `results.channels[].alternatives[].confidence` | Confidence score (0-1) | Yes |
## Environment Variables
```bash
# Your Deepgram API Key (for making requests)
DEEPGRAM_API_KEY=your_api_key_here
# API Key Identifier (shown in Deepgram console, used to verify dg-token)
# Note: This is NOT your API Key secret - it's a unique identifier shown
# in the Deepgram console that identifies which API key was used for a request
DEEPGRAM_API_KEY_ID=your_api_key_id_here
# Your webhook endpoint URL
WEBHOOK_URL=https://your-domain.com/webhooks/deepgram
```
## Local Development
For local webhook testing, install Hookdeck CLI:
```bash
# Install via npm
npm install -g hookdeck-cli
# Or via Homebrew
brew install hookdeck/hookdeck/hookdeck
# Create a local tunnel (no account required)
hookdeck listen 3000 --path /webhooks/deepgram
# Use the provided URL as your callback URL when making Deepgram requests
```
This provides:
- Local tunnel URL for testing
- Web UI for inspecting webhook payloads
- Request history and debugging tools
## Important Notes
### Retry Behavior
- Deepgram retries failed callbacks (non-200-299 status) up to 10 times
- 30-second delay between retry attempts
- Always return 200-299 status for successfully processed webhooks
### Port Restrictions
- Only ports 80, 443, 8080, and 8443 are allowed for callbacks
- Ensure your webhook endpoint uses one of these ports
### No Signature Verification
- Deepgram uses a simple token-based authentication via the dg-token header rather than cryptographic HMAC signatures used by other providers
- Authentication relies on the `dg-token` header or Basic Auth
- Always use HTTPS for webhook endpoints
## Resources
- [overview.md](references/overview.md) - What Deepgram webhooks are, transcription events
- [setup.md](references/setup.md) - Configure callbacks in Deepgram API requests
- [verification.md](references/verification.md) - Authentication methods and security considerations
- [examples/](examples/) - Complete implementations for Express, Next.js, and FastAPI
## Recommended: webhook-handler-patterns
For production handlers, install the patterns skill alongside this one. Key references (links work when only this skill is installed):
- [Idempotency](https://github.com/hookdeck/webhook-skills/blob/main/skills/webhook-handler-patterns/references/idempotency.md)
- [Error handling](https://github.com/hookdeck/webhook-skills/blob/main/skills/webhook-handler-patterns/references/error-handling.md)
- [Retry logic](https://github.com/hookdeck/webhook-skills/blob/main/skills/webhook-handler-patterns/references/retry-logic.md)
## Related Skills
- [stripe-webhooks](https://github.com/hookdeck/webhook-skills/tree/main/skills/stripe-webhooks) - Stripe payment webhooks
- [shopify-webhooks](https://github.com/hookdeck/webhook-skills/tree/main/skills/shopify-webhooks) - Shopify store webhooks
- [github-webhooks](https://github.com/hookdeck/webhook-skills/tree/main/skills/github-webhooks) - GitHub repository webhooks
- [webhook-handler-patterns](https://github.com/hookdeck/webhook-skills/tree/main/skills/webhook-handler-patterns) - Idempotency, error handling, retry logic
- [hookdeck-event-gateway](https://github.com/hookdeck/webhook-skills/tree/main/skills/hookdeck-event-gateway) - Webhook infrastructure that replaces your queue — guaranteed delivery, automatic retries, replay, rate limiting, and observability for your webhook handlers
---
## Referenced Files
> The following files are referenced in this skill and included for context.
### references/overview.md
```markdown
# Deepgram Webhooks Overview
## What Are Deepgram Webhooks?
Deepgram webhooks (called "callbacks" in their documentation) enable asynchronous processing of audio transcription requests. Instead of waiting for transcription to complete, you receive an immediate response with a `request_id`, and Deepgram sends the transcription results to your webhook URL when processing is finished.
## How Callbacks Work
1. **Submit Request**: Send audio to Deepgram API with a `callback` parameter
2. **Immediate Response**: Receive a `request_id` immediately
3. **Asynchronous Processing**: Deepgram processes your audio
4. **Webhook Delivery**: Transcription results are POSTed to your callback URL
## Common Use Cases
| Use Case | Description | Benefits |
|----------|-------------|----------|
| Large File Processing | Transcribe lengthy audio/video files | No timeout issues, better resource management |
| Batch Processing | Process multiple files concurrently | Higher throughput, parallel processing |
| Queue-Based Systems | Integrate with job queues | Decouple submission from processing |
| Real-time Notifications | Get notified when transcriptions complete | Update UI, trigger downstream processes |
| Resilient Architecture | Handle network interruptions gracefully | Automatic retries, guaranteed delivery |
## Webhook Payload Structure
The webhook payload contains the complete transcription response:
```json
{
"request_id": "uuid-string",
"created": "2024-01-20T10:30:00.000Z",
"duration": 120.5,
"channels": 1,
"model_info": {
"name": "general",
"version": "2024-01-09.29447",
"arch": "nova-2"
},
"results": {
"channels": [
{
"alternatives": [
{
"transcript": "Your transcribed text appears here...",
"confidence": 0.98765,
"words": [
{
"word": "Your",
"start": 0.0,
"end": 0.24,
"confidence": 0.99
}
// ... more word timings if requested
]
}
]
}
]
},
"metadata": {
// Any metadata you included in the request
}
}
```
## Features Available in Callbacks
All transcription features work with callbacks:
- **Punctuation**: Automatic punctuation insertion
- **Diarization**: Speaker identification
- **Word Timings**: Start/end times for each word
- **Language Detection**: Automatic language identification
- **Custom Vocabulary**: Domain-specific terms
- **Profanity Filtering**: Content moderation
- **Smart Formatting**: Numbers, dates, times formatting
## Callback vs Synchronous Requests
| Aspect | Synchronous | Callback (Webhook) |
|--------|-------------|-------------------|
| Response Time | Waits for completion | Immediate request_id |
| Timeout Risk | Yes, for long files | No |
| Resource Usage | Connection held open | Connection released immediately |
| Retry Logic | Client implements | Deepgram handles (10 retries) |
| Best For | Short audio (<60s) | Long audio, batch processing |
## Full Documentation
For complete details on all transcription features and options, see [Deepgram's API documentation](https://developers.deepgram.com/reference).
```
### references/setup.md
```markdown
# Setting Up Deepgram Webhooks
## Prerequisites
- Deepgram account with API access
- Your application's webhook endpoint URL (must use port 80, 443, 8080, or 8443)
- Deepgram API key from your console
## Get Your API Credentials
1. Log into [Deepgram Console](https://console.deepgram.com/)
2. Navigate to API Keys section
3. Create or select an API key
4. Note both:
- **API Key**: Used for authentication when making requests
- **API Key ID**: Shown in console, used to verify `dg-token` header
## Configure Your Webhook Endpoint
### 1. Create Your Endpoint
Your webhook endpoint should:
- Accept POST requests
- Use one of the allowed ports (80, 443, 8080, 8443)
- Return 200-299 status for successful processing
- Handle JSON payloads with transcription results
### 2. Add Callback to Your Requests
Include the `callback` parameter when making transcription requests:
```bash
# Basic callback
curl -X POST \
--header "Authorization: Token YOUR_API_KEY" \
--header "Content-Type: audio/wav" \
--data-binary @audio.wav \
"https://api.deepgram.com/v1/listen?callback=https://your-domain.com/webhooks/deepgram"
# With additional features
curl -X POST \
--header "Authorization: Token YOUR_API_KEY" \
--header "Content-Type: audio/wav" \
--data-binary @audio.wav \
"https://api.deepgram.com/v1/listen?callback=https://your-domain.com/webhooks/deepgram&punctuate=true&diarize=true"
```
### 3. Using Basic Auth (Optional)
For additional security, embed credentials in your callback URL:
```bash
# Format: https://username:password@domain/path
curl -X POST \
--header "Authorization: Token YOUR_API_KEY" \
--header "Content-Type: audio/wav" \
--data-binary @audio.wav \
"https://api.deepgram.com/v1/listen?callback=https://myuser:[email protected]/webhooks/deepgram"
```
## Testing Your Setup
### 1. Local Development with Hookdeck
```bash
# Install Hookdeck CLI
brew install hookdeck/hookdeck/hookdeck
# Create local tunnel
hookdeck listen 3000 --path /webhooks/deepgram
# Use the provided URL in your Deepgram requests
```
### 2. Send a Test Request
```bash
# Download a sample audio file
curl -O https://www.deepgram.com/examples/nasa-apollo-11.wav
# Send transcription request with callback
curl -X POST \
--header "Authorization: Token YOUR_API_KEY" \
--header "Content-Type: audio/wav" \
--data-binary @nasa-apollo-11.wav \
"https://api.deepgram.com/v1/listen?callback=YOUR_WEBHOOK_URL"
```
### 3. Verify the Response
You should receive:
1. Immediate response with `request_id`
2. Webhook POST to your endpoint within seconds/minutes (depending on file size)
3. Complete transcription results in the webhook payload
## Adding Metadata
Include custom metadata that will be returned in the webhook:
```bash
curl -X POST \
--header "Authorization: Token YOUR_API_KEY" \
--header "Content-Type: audio/wav" \
--data-binary @audio.wav \
"https://api.deepgram.com/v1/listen?callback=https://your-domain.com/webhooks/deepgram" \
--data '{
"metadata": {
"user_id": "123",
"session_id": "abc-def",
"custom_field": "value"
}
}'
```
## Webhook Method Configuration
By default, callbacks use POST. To use PUT instead:
```bash
curl -X POST \
--header "Authorization: Token YOUR_API_KEY" \
--header "Content-Type: audio/wav" \
--data-binary @audio.wav \
"https://api.deepgram.com/v1/listen?callback=https://your-domain.com/webhooks/deepgram&callback_method=put"
```
## Monitoring and Debugging
### Check Request Status
Use the request_id to check transcription status:
```bash
curl -X GET \
--header "Authorization: Token YOUR_API_KEY" \
"https://api.deepgram.com/v1/listen/YOUR_REQUEST_ID"
```
### Common Issues
1. **Webhook not received**: Check port restrictions (must be 80, 443, 8080, or 8443)
2. **Authentication failures**: Verify your API Key ID matches the `dg-token` header
3. **Repeated webhooks**: Ensure you return 200-299 status; Deepgram retries on errors
4. **Timeout errors**: Deepgram waits for response; process asynchronously if needed
```
### references/verification.md
```markdown
# Deepgram Webhook Verification
## Authentication Methods
Deepgram provides two methods to authenticate webhook callbacks:
### 1. dg-token Header (Recommended)
Every webhook request from Deepgram includes a `dg-token` header containing the API Key Identifier that was used to make the original transcription request.
```javascript
// Verify dg-token header
function verifyDeepgramWebhook(req) {
const dgToken = req.headers['dg-token'];
if (!dgToken) {
throw new Error('Missing dg-token header');
}
// Compare with your stored API Key ID
if (dgToken !== process.env.DEEPGRAM_API_KEY_ID) {
throw new Error('Invalid dg-token');
}
return true;
}
```
### 2. Basic Authentication
Embed credentials directly in your callback URL:
```javascript
// When making the request
const callbackUrl = `https://username:[email protected]/webhooks/deepgram`;
// In your webhook handler (Express example)
app.use('/webhooks/deepgram', express.basicAuth('username', 'password'));
```
## Implementation Examples
### Express.js Middleware
```javascript
const verifyDeepgramWebhook = (req, res, next) => {
try {
const dgToken = req.headers['dg-token'];
const expectedToken = process.env.DEEPGRAM_API_KEY_ID;
if (!dgToken || dgToken !== expectedToken) {
return res.status(403).json({ error: 'Invalid webhook authentication' });
}
next();
} catch (error) {
console.error('Webhook verification failed:', error);
res.status(403).json({ error: 'Webhook verification failed' });
}
};
// Use the middleware
app.post('/webhooks/deepgram',
express.raw({ type: 'application/json' }),
verifyDeepgramWebhook,
(req, res) => {
// Process webhook
const payload = JSON.parse(req.body);
console.log('Verified webhook received:', payload.request_id);
res.status(200).send('OK');
}
);
```
### Next.js API Route
```typescript
export async function POST(request: Request) {
// Verify dg-token
const dgToken = request.headers.get('dg-token');
if (!dgToken || dgToken !== process.env.DEEPGRAM_API_KEY_ID) {
return new Response('Unauthorized', { status: 403 });
}
// Process webhook
const payload = await request.json();
console.log('Verified webhook received:', payload.request_id);
return new Response('OK', { status: 200 });
}
```
### FastAPI Dependency
```python
from fastapi import Header, HTTPException, Depends
import os
async def verify_deepgram_webhook(dg_token: str = Header(None, alias="dg-token")):
"""Verify Deepgram webhook authentication"""
expected_token = os.environ.get("DEEPGRAM_API_KEY_ID")
if not dg_token or dg_token != expected_token:
raise HTTPException(status_code=403, detail="Invalid webhook authentication")
return True
# Use the dependency
@app.post("/webhooks/deepgram")
async def handle_deepgram_webhook(
payload: dict,
authenticated: bool = Depends(verify_deepgram_webhook)
):
print(f"Verified webhook received: {payload.get('request_id')}")
return {"status": "ok"}
```
## Security Considerations
### No Signature Verification
Unlike many webhook providers, Deepgram does **not** use cryptographic signatures (HMAC-SHA256) for webhook verification. This means:
- No timestamp validation
- No replay attack protection
- No payload integrity verification
### Best Practices
1. **Always use HTTPS**: Ensures webhook data is encrypted in transit
2. **Validate the dg-token**: Compare against your known API Key ID
3. **Store tokens securely**: Keep API Key IDs in environment variables
4. **Implement idempotency**: Track `request_id` to prevent duplicate processing
5. **Add rate limiting**: Protect against potential abuse
6. **Log authentication failures**: Monitor for suspicious activity
### Additional Security Layers
Consider adding your own security measures:
```javascript
// Add request timestamp validation
app.post('/webhooks/deepgram', (req, res) => {
const dgToken = req.headers['dg-token'];
const requestTime = req.headers['x-request-time'];
// Verify token
if (dgToken !== process.env.DEEPGRAM_API_KEY_ID) {
return res.status(403).send('Invalid token');
}
// Optional: Add timestamp validation
if (requestTime) {
const now = Date.now();
const requestTimestamp = parseInt(requestTime);
const MAX_AGE_MS = 5 * 60 * 1000; // 5 minutes
if (Math.abs(now - requestTimestamp) > MAX_AGE_MS) {
return res.status(403).send('Request too old');
}
}
// Process webhook
res.status(200).send('OK');
});
```
## Debugging Authentication Issues
### Common Problems
1. **Missing dg-token header**
- Ensure you're checking the correct header name
- Headers might be lowercase in some frameworks
2. **Token mismatch**
- Verify you're using the API Key ID (from console), not the API Key itself
- Check for whitespace or encoding issues
3. **Basic Auth not working**
- Ensure URL encoding for special characters
- Verify your framework supports Basic Auth parsing
### Debug Logging
```javascript
app.post('/webhooks/deepgram', (req, res) => {
console.log('Webhook headers:', req.headers);
console.log('dg-token:', req.headers['dg-token']);
console.log('Expected:', process.env.DEEPGRAM_API_KEY_ID);
// Rest of verification logic
});
```
## Summary
While Deepgram's webhook authentication is simpler than signature-based verification, it's important to:
1. Always verify the `dg-token` header
2. Use HTTPS for all webhook endpoints
3. Implement proper error handling and logging
4. Consider additional security measures based on your requirements
```