Skip to main content
The NDNC webhook pushes real-time UCC (Unsolicited Commercial Communication) complaint alerts to your own systems. Whenever a complaint is processed against your account, Vobiz sends a signed POST request to your HTTPS endpoint with the complaint details, so you can react immediately - pause a campaign, scrub a number, or open an internal ticket - instead of waiting to discover it in the console.
This is a webhook you receive, not a REST endpoint you call. It is activated manually by the Vobiz team - there is no self-serve API to register it yet. See UCC Management for the regulatory background on complaints and NDNC.

Activate the webhook

To turn on notifications, email your webhook URL and shared secret to ndnc@vobiz.ai, keeping piyush@vobiz.ai and goutham@vobiz.ai in CC.
1

Prepare what you'll send

#WhatExample
1Webhook URL - your HTTPS endpoint that will receive complaintshttps://hooks.yourcompany.com/vobiz-complaints
2Shared secret - a string you generate, used to sign requestsyour_secret_key_here
2

Email the Vobiz team

Send both values to ndnc@vobiz.ai, with piyush@vobiz.ai and goutham@vobiz.ai in CC.

Email ndnc@vobiz.ai (CC piyush, goutham)

Opens a pre-addressed email - just fill in your webhook URL and shared secret.
3

Wait for confirmation

The Vobiz team registers your endpoint and confirms once notifications are live.
Treat the shared secret like a password - send it only to ndnc@vobiz.ai over email, never paste it into client-side code, screenshots, or public repositories.

How it works

When a complaint is processed against your account, Vobiz sends a POST request to your webhook URL with the complaint details in JSON. All requests originate from a single, dedicated IP address.
Vobiz outbound IP: 15.207.141.89 - whitelist this on your firewall if your infrastructure requires it.
PropertyValue
MethodPOST
Content-Typeapplication/json
Signature headerX-VoBiz-Signature
Timeout5 seconds
Origin IP15.207.141.89

Payload structure

Every webhook POST contains a JSON body in this format:
Example payload
{
  "accountName": "Your Company Name",
  "totalComplaints": 2,
  "complaints": [
    {
      "urn": "XXXXXXXXXXXXXXXXXXXXXXXXX",
      "did": "9876543210",
      "complainantNumber": "9123456789",
      "complaintDate": "2026-06-08",
      "description": "Received telemarketing call in the SPAM category",
      "accountId": "MA_XXXXXXXX",
      "accountName": "Your Company Name",
      "accountEmail": "contact@yourcompany.com"
    }
  ]
}

Field reference

FieldTypeDescription
accountNamestringYour registered account name with Vobiz.
totalComplaintsintegerTotal number of complaints in this notification.
complaintsarrayList of individual complaint records.
complaints[].urnstringUnique system reference number assigned by the regulator.
complaints[].didstringThe DID (phone number) the complaint is against, without country code.
complaints[].complainantNumberstringThe complainant’s phone number.
complaints[].complaintDatestringDate the complaint was filed (YYYY-MM-DD).
complaints[].descriptionstringShort description / category of the complaint.
complaints[].accountIdstringYour Vobiz account ID.
complaints[].accountNamestringYour Vobiz account name.
complaints[].accountEmailstringYour registered email on the Vobiz account.

Verifying the signature

Every request includes an X-VoBiz-Signature header - an HMAC-SHA256 signature computed over the request body using your shared secret. Always verify it before processing any payload.
How the signature is computed
X-VoBiz-Signature = HMAC-SHA256(shared_secret, raw_request_body)
The body is serialised as compact JSON with no extra spaces before signing. Verify against the raw request body bytes - never re-serialise parsed JSON.
const crypto = require('crypto');

function verifyVobizWebhook(rawBody, receivedSignature, sharedSecret) {
  const expected = crypto
    .createHmac('sha256', sharedSecret)
    .update(rawBody) // raw body bytes — do not re-serialise
    .digest('hex');
  return crypto.timingSafeEqual(
    Buffer.from(expected),
    Buffer.from(receivedSignature)
  );
}

app.post('/vobiz-complaints', express.raw({ type: 'application/json' }), (req, res) => {
  const sig = req.headers['x-vobiz-signature'];
  if (!verifyVobizWebhook(req.body, sig, 'YOUR_SHARED_SECRET'))
    return res.status(401).send('Invalid signature');

  const data = JSON.parse(req.body);
  res.status(200).send('OK');
});
Always verify against the raw request body bytes - never re-serialise parsed JSON. Use a timing-safe comparison (hmac.compare_digest / timingSafeEqual) to prevent timing attacks.

Responding to a webhook

Your endpoint must return an HTTP 2xx status (e.g. 200 OK) within 5 seconds to acknowledge receipt. If your processing takes longer, acknowledge immediately and handle the data asynchronously in the background.

Choosing a strong shared secret

Your shared secret is the key used to sign every notification. Keep it confidential - treat it like a password.
  • Use a randomly generated string of at least 32 characters.
  • Generate one with openssl rand -hex 32.
  • Do not reuse passwords or other credentials as the secret.
  • Never expose it in client-side code or public repositories.

Setup checklist

1

Stand up an HTTPS endpoint

Accept POST requests with a JSON body.
2

Generate a strong shared secret

Run openssl rand -hex 32.
3

Send your details to Vobiz

Email your webhook URL and shared secret to ndnc@vobiz.ai, CC piyush@vobiz.ai and goutham@vobiz.ai.
4

Whitelist the origin IP

Allow 15.207.141.89 on your firewall if required.
5

Verify signatures

Implement X-VoBiz-Signature verification using your shared secret.
6

Acknowledge quickly

Return HTTP 200 within 5 seconds of receiving a webhook.
For questions or setup assistance, contact ndnc@vobiz.ai.