Skip to main content
After every call Neuron completes, your CRM should reflect what happened — lead status updated, call notes logged, transcript attached, QA score filed. Doing this manually is slow, error-prone, and simply doesn’t scale when you’re running thousands of calls a day. VInfer gives you two primary integration paths — real-time webhooks and REST API polling — plus native connectors for popular CRM platforms. This guide walks you through each approach so your CRM stays in sync without any manual intervention.

Why CRM Integration Matters

Eliminate Manual Updates

Without integration, agents must manually update lead status, paste call notes, and attach recordings after each call — at scale, this is unsustainable and introduces data lag.

Real-Time Lead Status

With webhooks, your CRM reflects the call outcome seconds after the call ends — “interested” contacts move to Hot Lead instantly, so your sales team can act while intent is fresh.

Full Conversation Context

Push transcripts, QA scores, and NeuronLens summaries directly to the contact record so anyone on your team has the full picture without listening to a recording.

Closed-Loop Reporting

Combine VInfer disposition data with your CRM pipeline metrics to measure actual revenue impact of your outbound and inbound campaigns end to end.

Integration Methods


Setting Up Webhook-Based CRM Sync

1
Create a Webhook Endpoint in Your CRM
2
Your CRM (or a middleware tool like Zapier, Make, or a custom API server) must expose a public HTTPS endpoint that can receive POST requests from VInfer. This endpoint will receive a JSON payload for each call event.
3
If you’re using middleware:
4
  • Zapier: Create a new Zap with a Webhook by Zapier trigger (Catch Hook), copy the generated URL.
  • Make (formerly Integromat): Add a Webhooks → Custom Webhook module, copy the generated URL.
  • Custom server: Set up a POST route at a path like /api/vinfer-events and ensure it’s accessible over HTTPS from the public internet.
  • 5
    Your endpoint must return a 200 OK HTTP response within 10 seconds of receiving the request. VInfer will retry delivery up to 3 times with exponential backoff if it receives a non-2xx response or a timeout.
    6
    7
    Register the Webhook with VInfer
    8
    Once your endpoint is ready, register it with VInfer so the platform knows where to send events:
    9
    cURL
    curl -X POST https://api.vinfer.ai/v1/webhooks \
      -H "Authorization: Bearer YOUR_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{
        "url": "https://your-crm.com/api/vinfer-events",
        "events": ["call.completed", "call.disposition_set"],
        "secret": "your_signing_secret"
      }'
    
    Python
    import requests
    
    response = requests.post(
        "https://api.vinfer.ai/v1/webhooks",
        headers={
            "Authorization": "Bearer YOUR_API_KEY",
            "Content-Type": "application/json"
        },
        json={
            "url": "https://your-crm.com/api/vinfer-events",
            "events": ["call.completed", "call.disposition_set"],
            "secret": "your_signing_secret"
        }
    )
    
    webhook = response.json()
    print(webhook["webhook_id"])
    
    Node.js
    const response = await fetch("https://api.vinfer.ai/v1/webhooks", {
      method: "POST",
      headers: {
        "Authorization": "Bearer YOUR_API_KEY",
        "Content-Type": "application/json"
      },
      body: JSON.stringify({
        url: "https://your-crm.com/api/vinfer-events",
        events: ["call.completed", "call.disposition_set"],
        secret: "your_signing_secret"
      })
    });
    
    const webhook = await response.json();
    console.log(webhook.webhook_id);
    
    10
    Available webhook events:
    11
    EventWhen It Firescall.completedEvery time a call ends (connected or not)call.disposition_setWhen Neuron or a human agent sets a dispositioncall.escalatedWhen a call is transferred to a human agentcall.transcription_readyWhen the NeuronLens transcript is available (may be a few minutes after call end)campaign.completedWhen an entire campaign finishes
    12
    Subscribe only to the events you actually need. Subscribing to all events on high-volume campaigns generates a large number of webhook deliveries — if your endpoint has processing overhead, narrow your subscription to the events that drive CRM actions.
    13
    14
    Verify Webhook Signatures
    15
    Every webhook request VInfer sends includes an X-VInfer-Signature header. Always verify this signature before processing the payload — it confirms the request genuinely came from VInfer and hasn’t been tampered with.
    16
    VInfer generates the signature using HMAC-SHA256 of the raw request body, keyed with the secret you provided during webhook registration.
    17
    Python
    import hmac
    import hashlib
    
    def verify_vinfer_signature(raw_body: bytes, signature_header: str, secret: str) -> bool:
        expected = hmac.new(
            key=secret.encode("utf-8"),
            msg=raw_body,
            digestmod=hashlib.sha256
        ).hexdigest()
        return hmac.compare_digest(expected, signature_header)
    
    # In your webhook handler:
    raw_body = request.get_data()  # raw bytes, before JSON parsing
    signature = request.headers.get("X-VInfer-Signature")
    
    if not verify_vinfer_signature(raw_body, signature, "your_signing_secret"):
        return Response("Unauthorized", status=401)
    
    payload = request.get_json()
    # proceed to process payload...
    
    Node.js
    const crypto = require("crypto");
    
    function verifyVInferSignature(rawBody, signatureHeader, secret) {
      const expected = crypto
        .createHmac("sha256", secret)
        .update(rawBody)
        .digest("hex");
      return crypto.timingSafeEqual(
        Buffer.from(expected),
        Buffer.from(signatureHeader)
      );
    }
    
    // In your Express webhook handler:
    app.post("/api/vinfer-events", express.raw({ type: "application/json" }), (req, res) => {
      const signature = req.headers["x-vinfer-signature"];
      
      if (!verifyVInferSignature(req.body, signature, "your_signing_secret")) {
        return res.status(401).send("Unauthorized");
      }
      
      const payload = JSON.parse(req.body);
      // proceed to process payload...
      res.sendStatus(200);
    });
    
    18
    Always use a timing-safe comparison function (like hmac.compare_digest in Python or crypto.timingSafeEqual in Node.js) when comparing signatures. Standard string equality is vulnerable to timing attacks.
    19
    20
    Map VInfer Disposition Values to Your CRM Fields
    21
    VInfer uses its own set of disposition values. You need to translate these to the corresponding field values in your CRM. Do this mapping in Settings → Integrations → CRM Mapping in the VInfer dashboard, or handle it in your webhook processing logic.
    22
    Example disposition mapping:
    23
    VInfer DispositionCRM Lead StatusinterestedHot Leadcallback_requestedFollow Upnot_interestedClosed Lostnot_reachableAttempted – No AnswerdisputeEscalatedpayment_promisedPromise to Payalready_paidResolved
    24
    If you use the dashboard mapping tool, VInfer automatically translates dispositions before sending the webhook payload — your CRM receives the mapped values directly and requires no transformation logic.
    25
    26
    Handle the Event Payload in Your CRM
    27
    Here is an example call.completed event payload. Use this as a reference when building your webhook handler:
    28
    {
      "event": "call.completed",
      "call_id": "call_abc123",
      "campaign_id": "camp_xyz456",
      "contact": {
        "phone": "+919876543210",
        "name": "Priya Sharma"
      },
      "disposition": "interested",
      "duration_seconds": 145,
      "language": "hi-IN",
      "timestamp": "2024-01-15T10:35:22Z",
      "transcript_url": "https://api.vinfer.ai/v1/transcription/job_def789/transcript",
      "neuronlens": {
        "sentiment": "positive",
        "qa_score": 87,
        "summary": "Customer confirmed interest in the top-up loan product. Requested a callback from the sales team before 3 PM today."
      }
    }
    
    29
    Recommended CRM update actions per event:
    30

    On call.completed

    1. Find the contact record by matching contact.phone
    2. Update Lead Status using the disposition mapping
    3. Log a call activity with duration_seconds, language, and timestamp
    4. Attach the transcript_url to the contact record for one-click access
    5. Store call_id in a custom field for future API lookups
    6. If disposition is callback_requested, create a follow-up task with the requested callback time
    31

    On call.transcription_ready

    Fetch the full transcript from transcript_url using your API key and attach it as a note to the contact record. This fires a few minutes after call.completed since transcription processing takes additional time.
    32

    On call.escalated

    Create an urgent follow-up task and notify the assigned account owner that the call was escalated. Log the escalation reason from the trigger field in the payload.

    REST API Polling

    If webhooks aren’t an option, poll the VInfer API on a schedule to fetch completed calls:
    curl "https://api.vinfer.ai/v1/calls?status=completed&after=2024-01-15T10:00:00Z&limit=100" \
      -H "Authorization: Bearer YOUR_API_KEY"
    
    Use the after parameter to fetch only calls completed since your last poll timestamp. Store the timestamp of the most recent call you processed and use it as after in your next poll to avoid re-processing records.
    If you poll frequently (every 1–2 minutes) on high-volume campaigns, be mindful of API rate limits. Check your account’s rate limit headers (X-RateLimit-Remaining) in the response and back off if you approach the limit.

    Storing the Call ID in Your CRM

    Always store VInfer’s call_id in a custom field on your CRM contact or activity record. This gives you a direct lookup key if you ever need to fetch the full call record, re-download the transcript, or cross-reference a dispute — without searching by phone number or timestamp.
    With the call_id, you can fetch any call’s full details at any time:
    curl https://api.vinfer.ai/v1/calls/call_abc123 \
      -H "Authorization: Bearer YOUR_API_KEY"