Skip to main content

Webhooks - Batch API

Receive notifications when transcriptions complete instead of polling.

Overview

Webhooks allow you to:

  • Eliminate status polling
  • Reduce API calls
  • Get instant notifications
  • Build event-driven workflows

Setup

1. Configure Webhook URL

Provide webhook_url when uploading:

curl -X POST https://api.scriptix.io/api/v3/stt \
-H "Authorization: Bearer YOUR_API_KEY" \
-F "language=en" \
-F "webhook_url=https://yourapp.com/webhook" \
-F "audio_file=@audio.mp3"

2. Receive Webhook

Your endpoint receives POST request when transcription completes:

POST /webhook HTTP/1.1
Host: yourapp.com
Content-Type: application/json
X-Scriptix-Signature: sha256=abc123...

{
"event": "transcription.completed",
"timestamp": "2025-01-17T10:30:00Z",
"data": {
"id": "stt_abc123",
"status": "completed",
"document_id": 456
}
}

Webhook Events

EventTrigger
transcription.completedTranscription finished successfully
transcription.failedTranscription failed with error

Webhook Payload

{
"event": "transcription.completed",
"timestamp": "2025-01-17T10:30:00Z",
"data": {
"id": "stt_abc123",
"status": "completed",
"document_id": 456,
"duration_seconds": 3600,
"language": "en"
}
}

Webhook Signature

Verify webhook authenticity using X-Scriptix-Signature header:

Python Verification

import hmac
import hashlib

def verify_webhook(payload, signature, secret):
"""Verify webhook signature."""
expected = hmac.new(
secret.encode(),
payload.encode(),
hashlib.sha256
).hexdigest()

return hmac.compare_digest(f"sha256={expected}", signature)

# Usage
@app.route('/webhook', methods=['POST'])
def webhook():
payload = request.data.decode()
signature = request.headers.get('X-Scriptix-Signature')

if not verify_webhook(payload, signature, WEBHOOK_SECRET):
return 'Invalid signature', 401

data = request.json()

if data['event'] == 'transcription.completed':
job_id = data['data']['id']
document_id = data['data']['document_id']
# Process completed transcription
process_completed(job_id, document_id)

return 'OK', 200

Node.js Verification

const crypto = require('crypto');

function verifyWebhook(payload, signature, secret) {
const expected = crypto
.createHmac('sha256', secret)
.update(payload)
.digest('hex');

return crypto.timingSafeEqual(
Buffer.from(`sha256=${expected}`),
Buffer.from(signature)
);
}

app.post('/webhook', (req, res) => {
const payload = JSON.stringify(req.body);
const signature = req.headers['x-scriptix-signature'];

if (!verifyWebhook(payload, signature, WEBHOOK_SECRET)) {
return res.status(401).send('Invalid signature');
}

const { event, data } = req.body;

if (event === 'transcription.completed') {
processCompleted(data.id, data.document_id);
}

res.send('OK');
});

Best Practices

1. Return 200 OK Quickly

Process webhook asynchronously:

@app.route('/webhook', methods=['POST'])
def webhook():
data = request.json()

# Queue for async processing
queue.enqueue(process_webhook, data)

# Return immediately
return 'OK', 200

def process_webhook(data):
# Long-running processing here
pass

2. Implement Idempotency

Handle duplicate webhooks:

processed_webhooks = set()

def process_webhook(data):
job_id = data['data']['id']

if job_id in processed_webhooks:
return # Already processed

# Process webhook
handle_transcription(job_id)

processed_webhooks.add(job_id)

3. Retry Failed Webhooks

Scriptix retries failed webhooks:

  • 3 retry attempts
  • Exponential backoff (1min, 5min, 15min)

Always return 200 OK for successful processing.

Testing Webhooks

Use Webhook Testing Tools

# Expose local server
ngrok http 3000

# Use ngrok URL in upload
-F "webhook_url=https://abc123.ngrok.io/webhook"

Test Payload

curl -X POST https://yourapp.com/webhook \
-H "Content-Type: application/json" \
-H "X-Scriptix-Signature: sha256=test123" \
-d '{
"event": "transcription.completed",
"timestamp": "2025-01-17T10:30:00Z",
"data": {
"id": "stt_test123",
"status": "completed",
"document_id": 999
}
}'

Troubleshooting

Webhook Not Received

Checklist:

  • ✅ URL publicly accessible?
  • ✅ HTTPS enabled? (required)
  • ✅ Firewall allows Scriptix IPs?
  • ✅ Returns 200 OK?
  • ✅ Response time < 30 seconds?

Signature Verification Fails

Common issues:

  • Using wrong webhook secret
  • Incorrect payload serialization
  • Timing attack in comparison