Webhooks

Voxxi can send event notifications to your endpoint when call processing completes or fails.

Overview

Configure webhook endpoints in Voxxi Integrations. Each endpoint subscribes to one or more events.

Event types

  • Name
    call.analysis_complete
    Description

    Fired when call analysis finishes successfully.

  • Name
    call.analysis_failed
    Description

    Fired when analysis fails.

  • Name
    call.ingestion_failed
    Description

    Fired when recording ingestion fails.

Headers

Webhook deliveries are POST requests with JSON body and these headers:

  • Name
    X-Voxxi-Event
    Type
    string
    Description

    Event name, for example call.analysis_complete.

  • Name
    X-Voxxi-Timestamp
    Type
    string
    Description

    Unix timestamp (seconds) used in signature generation.

  • Name
    X-Voxxi-Signature
    Type
    string
    Description

    Signature in the format v1=<hex_hmac_sha256>.

  • Name
    X-Voxxi-Delivery-Id
    Type
    string
    Description

    Unique id for this delivery attempt.

Payload envelope

{
  "id": "delivery_uuid",
  "type": "call.analysis_complete",
  "createdAt": "2026-01-01T00:00:00.000Z",
  "data": {
    "callId": "call_uuid",
    "organizationId": "org_uuid"
  }
}

data fields vary by event type. call.analysis_complete includes analysis results, transcript/extractions, tags, and metadata.

Event payload schemas

All webhook deliveries use the same top-level envelope:

  • Name
    id
    Type
    string
    Description

    Unique delivery id (UUID).

  • Name
    type
    Type
    string
    Description

    Webhook event type.

  • Name
    createdAt
    Type
    string
    Description

    ISO-8601 timestamp for delivery creation.

  • Name
    data
    Type
    object
    Description

    Event-specific payload. See schemas below.

call.analysis_complete

  • Name
    data.callId
    Type
    string
    Description

    Call id.

  • Name
    data.organizationId
    Type
    string
    Description

    Organization id.

  • Name
    data.memberId
    Type
    string | null
    Description

    Agent/member id.

  • Name
    data.memberName
    Type
    string | null
    Description

    Agent/member display name.

  • Name
    data.categoryId
    Type
    string | null
    Description

    Category id used for analysis.

  • Name
    data.duration
    Type
    number
    Description

    Call duration in seconds.

  • Name
    data.date
    Type
    string
    Description

    Call date (YYYY-MM-DD).

  • Name
    data.audioUrl
    Type
    string | null
    Description

    Recording URL.

  • Name
    data.udfs
    Type
    object | null
    Description

    User-defined fields attached to the call.

  • Name
    data.score
    Type
    number
    Description

    Overall analysis score.

  • Name
    data.outcomeLabel
    Type
    string | null
    Description

    Outcome label.

  • Name
    data.outcomeRationale
    Type
    string | null
    Description

    Explanation for outcome.

  • Name
    data.callObservations
    Type
    string | null
    Description

    Observations summary.

  • Name
    data.areasForImprovement
    Type
    string | null
    Description

    Improvement summary.

  • Name
    data.summary
    Type
    string | null
    Description

    Short call summary.

  • Name
    data.transcript
    Type
    array | null
    Description

    Array of transcript segments: { start, end, speaker, content }.

  • Name
    data.extractions
    Type
    array | null
    Description

    Extraction objects: { id, fieldName, displayName, value, fieldType, description, required, enumValues }.

  • Name
    data.analytics
    Type
    array
    Description

    Section-level scoring: { sectionId, sectionName, score, totalScore, criterias[] }.

  • Name
    data.uploadedBy
    Type
    string | null
    Description

    Uploader user id.

  • Name
    data.uploadedByName
    Type
    string | null
    Description

    Uploader name.

  • Name
    data.uploadedByEmail
    Type
    string | null
    Description

    Uploader email.

  • Name
    data.tags
    Type
    array
    Description

    Call tags: { id, slug, displayName, description }.

  • Name
    data.completedAt
    Type
    string
    Description

    ISO-8601 timestamp when analysis completed.

  • Name
    data.createdAt
    Type
    string
    Description

    ISO-8601 timestamp when call was created.

call.analysis_complete example

{
  "id": "4e7f0708-5418-48c8-bf68-06cfef58da9d",
  "type": "call.analysis_complete",
  "createdAt": "2026-04-09T07:30:00.000Z",
  "data": {
    "callId": "bff2f584-8bba-4fce-bc99-c5adf72f04a2",
    "organizationId": "25f7f786-f334-4f0c-9f0d-09d9aef6f37a",
    "memberId": "ee96ce4e-8f8a-4e87-8a7f-93ea7c2260e1",
    "memberName": "Ari Sharma",
    "categoryId": "e9862d12-d729-47ef-8173-99e4e2804c0f",
    "duration": 642,
    "date": "2026-04-09",
    "audioUrl": "https://cdn.example.com/calls/call-123.mp3",
    "udfs": {
      "leadId": "lead_123",
      "source": "website"
    },
    "score": 86,
    "outcomeLabel": "Qualified",
    "outcomeRationale": "Clear need, budget, and timeline captured.",
    "callObservations": "Strong discovery and objection handling.",
    "areasForImprovement": "Tighter next-step confirmation.",
    "summary": "Prospect agreed to product demo next week.",
    "transcript": [
      {
        "start": 0.12,
        "end": 4.33,
        "speaker": "agent",
        "content": "Thanks for taking the call today."
      }
    ],
    "extractions": [
      {
        "id": "ext_1",
        "fieldName": "budget",
        "displayName": "Budget",
        "value": "$12,000",
        "fieldType": "string",
        "description": "Customer-stated budget",
        "required": false,
        "enumValues": null
      }
    ],
    "analytics": [
      {
        "sectionId": "discovery",
        "sectionName": "Discovery",
        "score": 8,
        "totalScore": 10,
        "criterias": [
          {
            "criteriaId": "asked_pain_points",
            "question": "Did the agent uncover pain points?",
            "result": true,
            "rationale": "Customer pain points were clarified."
          }
        ]
      }
    ],
    "uploadedBy": "e535a336-2cb5-49a6-9292-d3670a52edba",
    "uploadedByName": "Priya Nair",
    "uploadedByEmail": "priya@example.com",
    "tags": [
      {
        "id": "76f8b94e-c18e-4ce4-b4c2-b78bc4cae4e6",
        "slug": "enterprise",
        "displayName": "Enterprise",
        "description": "Enterprise opportunity"
      }
    ],
    "completedAt": "2026-04-09T07:29:52.000Z",
    "createdAt": "2026-04-09T07:10:41.000Z"
  }
}

call.analysis_failed

  • Name
    data.callId
    Type
    string
    Description

    Call id.

  • Name
    data.organizationId
    Type
    string
    Description

    Organization id.

  • Name
    data.message
    Type
    string
    Description

    Failure reason summary.

  • Name
    data.failedAt
    Type
    string
    Description

    ISO-8601 failure timestamp.

call.analysis_failed example

{
  "id": "dff42aec-c880-472f-9df1-d16bdc77661e",
  "type": "call.analysis_failed",
  "createdAt": "2026-04-09T07:31:00.000Z",
  "data": {
    "callId": "bff2f584-8bba-4fce-bc99-c5adf72f04a2",
    "organizationId": "25f7f786-f334-4f0c-9f0d-09d9aef6f37a",
    "message": "Call analysis failed",
    "failedAt": "2026-04-09T07:30:58.000Z"
  }
}

call.ingestion_failed

  • Name
    data.callId
    Type
    string
    Description

    Call id.

  • Name
    data.organizationId
    Type
    string
    Description

    Organization id.

  • Name
    data.recordingUrl
    Type
    string
    Description

    Recording URL that failed ingestion.

  • Name
    data.errorMessage
    Type
    string
    Description

    Ingestion error details.

  • Name
    data.failedAt
    Type
    string
    Description

    ISO-8601 failure timestamp.

call.ingestion_failed example

{
  "id": "f554c715-cfd8-46fe-a3ca-4381e0263e91",
  "type": "call.ingestion_failed",
  "createdAt": "2026-04-09T07:32:00.000Z",
  "data": {
    "callId": "bff2f584-8bba-4fce-bc99-c5adf72f04a2",
    "organizationId": "25f7f786-f334-4f0c-9f0d-09d9aef6f37a",
    "recordingUrl": "https://cdn.example.com/calls/call-123.mp3",
    "errorMessage": "Unable to ingest recording",
    "failedAt": "2026-04-09T07:31:58.000Z"
  }
}

Signature verification

The signature is HMAC-SHA256 over:

<timestamp>.<raw_request_body>

using your webhook signing secret.

Verify X-Voxxi-Signature

import crypto from 'crypto'

function verifyVoxxiSignature({ secret, timestamp, rawBody, signatureHeader }) {
  const expected = crypto
    .createHmac('sha256', secret)
    .update(`${timestamp}.${rawBody}`)
    .digest('hex')

  const provided = signatureHeader?.replace(/^v1=/, '')
  return Boolean(provided) && crypto.timingSafeEqual(
    Buffer.from(expected, 'hex'),
    Buffer.from(provided, 'hex')
  )
}