Webhooks
Receive real-time HTTP notifications when transcription jobs complete or fail. Webhooks eliminate polling and let you build event-driven integrations.
Plan Limits
| Plan | Max Webhooks | Log Retention |
|---|---|---|
| Lite | 1 | 7 days |
| Pro | 5 | 30 days |
Event Types
| Event | Description |
|---|---|
transcription.completed | Job finished successfully |
transcription.failed | Job failed |
webhook.test | Test ping (manual trigger) |
Create a Webhook
curl
curl -X POST https://api.voxparse.com/v1/webhooks \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://your-app.com/webhooks/voxparse",
"events": ["transcription.completed", "transcription.failed"],
"description": "Production webhook"
}'
Important: The
secret field is shown only once in the response. Store it securely for signature verification.Endpoints
| Method | Path | Description |
|---|---|---|
POST | /v1/webhooks | Create webhook |
GET | /v1/webhooks | List webhooks |
PATCH | /v1/webhooks/:id | Update webhook |
DELETE | /v1/webhooks/:id | Delete webhook |
POST | /v1/webhooks/:id/test | Send test ping |
POST | /v1/webhooks/:id/rotate-secret | Rotate signing secret |
GET | /v1/webhooks/:id/deliveries | View delivery log |
Delivery Headers
| Header | Description |
|---|---|
X-VoxParse-Signature | HMAC-SHA256 hex signature |
X-VoxParse-Timestamp | ISO 8601 signing timestamp |
X-VoxParse-Event-Type | Event type |
X-VoxParse-Event-Id | Unique event ID (for idempotency) |
X-VoxParse-Delivery-Id | Unique delivery attempt ID |
X-VoxParse-Attempt | Attempt number (1-4) |
Signature Verification
Compute HMAC-SHA256(secret, timestamp + "." + body) and compare in constant time.
Node.js
import crypto from 'crypto';
function verifyWebhook(secret, timestamp, body, signature) {
const expected = crypto
.createHmac('sha256', secret)
.update(timestamp + '.' + body)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(expected, 'hex'),
Buffer.from(signature, 'hex')
);
}
Python
import hmac, hashlib
def verify_webhook(secret, timestamp, body, signature):
expected = hmac.new(
secret.encode(), f"{timestamp}.{body}".encode(), hashlib.sha256
).hexdigest()
return hmac.compare_digest(expected, signature)
Replay Protection: Reject requests where the timestamp is more than 5 minutes old.
Retry Policy
| Attempt | Delay |
|---|---|
| 1 | Immediate |
| 2 | ~30 seconds |
| 3 | ~5 minutes |
| 4 | ~30 minutes |
Auto-Disable
After 10 consecutive failures over at least 30 minutes, the webhook is auto-disabled. Re-enable via PATCH /v1/webhooks/:id with {"active": true}.
Async Transcription
Pass async=true to get a 202 Accepted response immediately. Combine with webhooks for fully non-blocking integrations.
curl
curl -X POST https://api.voxparse.com/v1/transcribe \
-H "X-API-Key: YOUR_API_KEY" \
-F [email protected] \
-F plan=pro \
-F async=true \
-F 'metadata={"crm_id":"deal-789"}'
Metadata Passthrough
Pass a metadata field (max 4 KB JSON) in your transcription request. It echoes in the webhook payload for correlation.
Security
- HTTPS only on port 443
- SSRF protection blocks private IPs, localhost, and cloud metadata endpoints
- Encrypted secrets at rest with AES-GCM
- No embedded credentials in webhook URLs
- 5-second timeout per delivery attempt