Webhooks
Receive real-time notifications when episodes complete or fail. Webhooks eliminate the need for polling and enable event-driven workflows.
Overview
LogTalk supports two types of webhooks:
webhook_url in your episode request. The callback is sent only for that specific episode. Ideal for CI/CD pipelines.Per-Request Webhooks
Include a webhook_url in your episode request to receive a callback when that specific episode completes:
curl -X POST https://api.logtalk.io/v1/episodes \-H "Authorization: Bearer lt_live_your_key" \-H "Content-Type: application/json" \-d '{"content": "## v2.0.0\n- New feature","output_format": "video","webhook_url": "https://your-app.com/webhooks/logtalk"}'
Note: Webhook URLs must use HTTPS. HTTP URLs will be rejected.
Event Types
| Event | Description |
|---|---|
episode.completed | Conversion finished successfully with media URLs |
episode.failed | Conversion failed with error details |
quota.warning | Approaching quota limit (80%) |
quota.exceeded | Monthly quota exceeded |
Webhook Payload
Webhooks are sent as POST requests with a JSON body:
episode.completed
{"id": "evt_abc123def456","type": "episode.completed","created_at": "2026-01-18T14:32:15.000Z","data": {"episode": {"id": "550e8400-e29b-41d4-a716-446655440000","output_format": "video","mode": "changelog","status": "completed","video_url": "https://cdn.logtalk.io/video/...","audio_url": "https://cdn.logtalk.io/audio/...","duration_seconds": 180,"version": "2.0.0","created_at": "2026-01-18T14:30:00.000Z","completed_at": "2026-01-18T14:32:15.000Z"}}}
episode.failed
{"id": "evt_abc123def456","type": "episode.failed","created_at": "2026-01-18T14:31:00.000Z","data": {"episode": {"id": "550e8400-e29b-41d4-a716-446655440000","output_format": "video","mode": "changelog","status": "failed","error": {"code": "GENERATION_FAILED","message": "Audio generation failed"},"created_at": "2026-01-18T14:30:00.000Z","failed_at": "2026-01-18T14:31:00.000Z"}}}
Webhook Headers
Each webhook request includes these headers:
| Header | Description |
|---|---|
Content-Type | Always application/json |
X-LogTalk-Event | Event type (e.g., episode.completed) |
X-LogTalk-Delivery | Unique delivery ID for debugging |
X-LogTalk-Signature | HMAC-SHA256 signature (format: t=timestamp,v1=signature) |
X-LogTalk-Timestamp | Unix timestamp when webhook was sent |
Signature Verification
Always verify webhook signatures to ensure requests are from LogTalk. Signatures use HMAC-SHA256 with the format t=timestamp,v1=signature.
${timestamp}.${JSON.stringify(payload)}This prevents replay attacks by binding the signature to the timestamp.
Verification Examples
const crypto = require('crypto');function verifyWebhookSignature(payload, signatureHeader, secret) {// Parse signature header: t=timestamp,v1=signatureconst parts = signatureHeader.split(',');const timestamp = parseInt(parts.find(p => p.startsWith('t=')).split('=')[1]);const signature = parts.find(p => p.startsWith('v1=')).split('=')[1];// Check timestamp (reject if > 5 minutes old)const now = Math.floor(Date.now() / 1000);if (Math.abs(now - timestamp) > 300) {throw new Error('Webhook timestamp too old');}// Compute expected signatureconst signedPayload = `${timestamp}.${JSON.stringify(payload)}`;const expectedSignature = crypto.createHmac('sha256', secret).update(signedPayload).digest('hex');// Use timing-safe comparisonreturn crypto.timingSafeEqual(Buffer.from(signature, 'hex'),Buffer.from(expectedSignature, 'hex'));}// Express.js exampleapp.post('/webhooks/logtalk', express.json(), (req, res) => {const signature = req.headers['x-logtalk-signature'];const secret = process.env.LOGTALK_WEBHOOK_SECRET;if (!verifyWebhookSignature(req.body, signature, secret)) {return res.status(401).send('Invalid signature');}// Process the webhookconst { type, data } = req.body;console.log(`Received ${type}: ${data.episode.id}`);res.status(200).send('OK');});
Retry Policy
If your endpoint returns a non-2xx status code or times out, LogTalk will retry with exponential backoff:
| Attempt | Delay |
|---|---|
| 1 | Immediate |
| 2 | 1 minute |
| 3 | 5 minutes |
| 4 | 30 minutes |
| 5 | 2 hours |
| 6 | 8 hours |
After 6 failed attempts, the webhook is marked as failing and you'll be notified via email. Webhook timeout is 30 seconds.
Best Practices
id to deduplicate events and ensure idempotent processing.X-LogTalk-Signature header to ensure webhooks are authentic and haven't been tampered with.