Receive and verify Deepgram webhooks (callbacks). Use when setting up Deepgram webhook handlers, processing transcription callbacks, or handling asynchronous transcription results.
68
85%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
Low
Low-risk findings worth noting
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.
// Express.js example
const crypto = require('crypto');
function safeEqual(a, b) {
const ab = Buffer.from(a || '', 'utf8');
const bb = Buffer.from(b || '', 'utf8');
return ab.length === bb.length && crypto.timingSafeEqual(ab, bb);
}
app.post('/webhooks/deepgram', express.raw({ type: 'application/json' }), (req, res) => {
// 1. Primary check: Basic Auth credentials you embedded in the callback URL
// (https://user:pass@your-domain.com/webhooks/deepgram)
const auth = req.headers['authorization'] || '';
const decoded = auth.startsWith('Basic ')
? Buffer.from(auth.slice(6), 'base64').toString('utf8')
: '';
const sep = decoded.indexOf(':');
if (
sep === -1 ||
!safeEqual(decoded.slice(0, sep), process.env.DEEPGRAM_CALLBACK_USERNAME) ||
!safeEqual(decoded.slice(sep + 1), process.env.DEEPGRAM_CALLBACK_PASSWORD)
) {
return res.status(401).send('Unauthorized');
}
// 2. Supplementary check: dg-token is NOT sent on every callback,
// so only compare it when it is present
const dgToken = req.headers['dg-token'];
if (dgToken && process.env.DEEPGRAM_API_KEY_ID && !safeEqual(dgToken, process.env.DEEPGRAM_API_KEY_ID)) {
return res.status(403).send('Invalid dg-token');
}
// The callback body is the normal /v1/listen response: { metadata, results }
const payload = JSON.parse(req.body.toString());
const requestId = payload.metadata?.request_id;
const transcript = payload.results?.channels?.[0]?.alternatives?.[0]?.transcript;
console.log('Received transcription:', requestId, transcript);
// Return success to prevent retries
res.status(200).send('OK');
});Deepgram documents two ways to authenticate callbacks:
Authorization: Basic header// Basic Auth in callback URL (percent-encode special characters in the credentials)
// https://username:password@your-domain.com/webhooks/deepgram
// dg-token: check only when present
const dgToken = req.headers['dg-token'];
if (dgToken && dgToken !== process.env.DEEPGRAM_API_KEY_ID) {
return res.status(403).send('Invalid dg-token');
}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://username:password@your-domain.com/webhooks/deepgram'Deepgram callbacks carry no event-type field. The body is the same JSON a synchronous /v1/listen request returns: a metadata object and a results object. The structure of results varies based on the features enabled in your request:
| Field | Description | Always Present |
|---|---|---|
metadata.request_id | Unique identifier for the transcription request (matches the request_id returned when you submitted it) | Yes |
metadata.created | Timestamp when transcription was created | Yes |
metadata.duration | Length of the audio in seconds | Yes |
metadata.channels | Number of audio channels | Yes |
metadata.extra | Key-value pairs you passed with extra=KEY:VALUE | Only if extra was sent |
results.channels[].alternatives | Transcription alternatives | Yes |
results.channels[].alternatives[].transcript | The transcribed text | Yes |
results.channels[].alternatives[].confidence | Confidence score (0-1) | Yes |
# Your Deepgram API Key (for making requests)
DEEPGRAM_API_KEY=your_api_key_here
# Basic Auth credentials you embed in the callback URL (primary check)
DEEPGRAM_CALLBACK_USERNAME=your_callback_username
DEEPGRAM_CALLBACK_PASSWORD=your_callback_password
# Optional: API Key Identifier, used to check the dg-token header when present
# 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/deepgramFor local webhook testing, install Hookdeck CLI:
# Create a local tunnel (no account required)
npx hookdeck-cli listen 3000 deepgram --path /webhooks/deepgram
# Use the provided URL as your callback URL when making Deepgram requestsThis provides:
dg-token header as a supplementary check because it is not sent on every callbackFor production handlers, install the patterns skill alongside this one. Key references (links work when only this skill is installed):
1b5cbf0
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.