Webhooks

Receive real-time HTTP notifications when transcription jobs complete or fail. Webhooks eliminate polling and let you build event-driven integrations.

Plan Limits

PlanMax WebhooksLog Retention
Lite17 days
Pro530 days

Event Types

EventDescription
transcription.completedJob finished successfully
transcription.failedJob failed
webhook.testTest 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

MethodPathDescription
POST/v1/webhooksCreate webhook
GET/v1/webhooksList webhooks
PATCH/v1/webhooks/:idUpdate webhook
DELETE/v1/webhooks/:idDelete webhook
POST/v1/webhooks/:id/testSend test ping
POST/v1/webhooks/:id/rotate-secretRotate signing secret
GET/v1/webhooks/:id/deliveriesView delivery log

Delivery Headers

HeaderDescription
X-VoxParse-SignatureHMAC-SHA256 hex signature
X-VoxParse-TimestampISO 8601 signing timestamp
X-VoxParse-Event-TypeEvent type
X-VoxParse-Event-IdUnique event ID (for idempotency)
X-VoxParse-Delivery-IdUnique delivery attempt ID
X-VoxParse-AttemptAttempt 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

AttemptDelay
1Immediate
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