Skip to main content
Plivo and Vobiz handle voice webhooks almost identically: both POST application/x-www-form-urlencoded callbacks with the same call params, and both sign each request with an HMAC keyed by your auth token plus a nonce. The two differences that matter: Vobiz sends Ring / StartApp / Hangup as events to the answer flow (no separate ring_url), and Vobiz V2/V3 sign only the base URL + nonce, while Plivo V3 also hashes the sorted POST params.

Callback URL & event mapping

PlivoVobizNotes
answer_url (mandatory)answer_url + answer_methodReturns XML to drive the call.
ring_url(no separate URL)Ring event to answer flowVobiz emits a Ring callback instead of a dedicated endpoint.
hangup_url + hangup_methodhangup_url + hangup_methodFire-and-forget end-of-call notification; also emits a Hangup event.
fallback_url / fallback_answer_urlfallback_answer_url + fallback_methodInvoked when the primary answer URL is unreachable.
action attribute (Dial, Record, GetInput…)action attribute (Dial, Record, Gather…)Expects an XML response to continue.
callbackUrl attribute (notify-only)callbackUrl / callback_url attributeAsync notification; no XML expected.
Event: answeredEvent: StartApp”Call answered.”
Event: hangupEvent: Hangup”Call ended.”
Event: ringingEvent: Ring”Call is ringing.”

Signature header mapping

PlivoVobizScheme
X-Plivo-Signature-V3X-Vobiz-Signature-V3HMAC-SHA256, base64. Signs baseURL + "." + nonce.
X-Plivo-Signature-V3-NonceX-Vobiz-Signature-V3-NonceRandom nonce for the V3 signature.
(no equivalent)X-Vobiz-Signature-V2 (+ -Nonce)HMAC-SHA256, base64. Signs baseURL + nonce (no .).
X-Plivo-Signature-Ma-V3X-Vobiz-Signature-MA-V3Same scheme, signed with the main (parent) account token on sub-account callbacks.
X-Plivo-Signature-V2 (legacy SHA1)X-Vobiz-Signature (legacy SHA1)Backwards compatibility only — avoid.
The signed strings are not byte-identical. Plivo V3 signs the full URL + sorted POST params + nonce; Vobiz V3 strips query params and signs only baseURL + "." + nonce. You cannot reuse Plivo’s validate_v3_signature(...) against Vobiz headers — use the HMAC below.

Before / after: verifying the signature

Plivo ships a helper; on Vobiz verification is a few lines of stdlib HMAC (the vobiz SDK is for the REST API, not webhook validation).
Python (Flask)
# ---------- BEFORE: Plivo ----------
import plivo
from flask import request, abort

AUTH_TOKEN = "your_plivo_auth_token"

@app.route("/webhook", methods=["POST"])
def webhook_plivo():
    valid = plivo.utils.validate_v3_signature(
        request.method,
        request.url,
        request.headers.get("X-Plivo-Signature-V3-Nonce", ""),
        AUTH_TOKEN,
        request.headers.get("X-Plivo-Signature-V3", ""),
        request.form.to_dict(),   # Plivo hashes the POST params too
    )
    if not valid:
        abort(403, "Invalid signature")
    # ... handle event

# ---------- AFTER: Vobiz ----------
import hmac, hashlib, base64
from urllib.parse import urlparse, urlunparse
from flask import request, abort

AUTH_TOKEN = "your_vobiz_auth_token"

def base_url(url: str) -> str:
    p = urlparse(url)
    return urlunparse((p.scheme, p.netloc, p.path, "", "", ""))  # strip query

def validate(url, token, headers, v3=True):
    sep = "." if v3 else ""
    sig_h   = "X-Vobiz-Signature-V3" if v3 else "X-Vobiz-Signature-V2"
    nonce_h = sig_h + "-Nonce"
    msg = (base_url(url) + sep + headers.get(nonce_h, "")).encode()
    expected = base64.b64encode(
        hmac.new(token.encode(), msg, hashlib.sha256).digest()
    ).decode()
    return hmac.compare_digest(headers.get(sig_h, ""), expected)

@app.route("/webhook", methods=["POST"])
def webhook_vobiz():
    if not validate(request.url, AUTH_TOKEN, request.headers, v3=True):
        abort(403, "Invalid signature")
    event = request.form.get("Event")   # Ring | StartApp | Hangup
    # ... handle event
    return "", 200
Callback params are the same names you read from Plivo — CallUUID, From, To, Direction, CallStatus, HangupCause, Duration, plus Event / timestamp / auth_id on every callback. See the Vobiz XML request params and Callbacks reference.

Key differences & gotchas

  • Different signed string. Vobiz V2/V3 hash only the base URL + nonce, so the signature proves origin and URL, not body integrity — treat param values defensively.
  • Events instead of dedicated URLs. Branch on the Event field for Ring, StartApp, and Hangup rather than registering separate ring_url / hangup_url.
  • Header casing & compares. Nonces are 20-digit strings; read headers case-insensitively and compare with hmac.compare_digest / crypto.timingSafeEqual, never ==.
  • Main-account (MA) signatures. Sub-account callbacks add a parent-signed header (X-Vobiz-Signature-MA-V3) — reuse the validator with the parent token.

What has no direct equivalent

  • No SDK signature helper on Vobiz. Plivo bundles validate_v3_signature / validateV3Signature; the Vobiz SDKs do not ship a webhook validator — use the stdlib HMAC snippet above.
  • No comma-separated multi-token signatures. Plivo concatenates signatures for multiple active tokens in one header; Vobiz documents a single signature per scheme (plus the MA variant). Rotate the token rather than running two in parallel.
  • No dedicated ring_url endpoint. There is no separate ring callback URL — the Ring event is delivered through the answer flow.

Validating callbacks

Canonical Vobiz signature reference with Python, Node, Go, and Ruby.

Migration gotchas

Edge cases when moving from Plivo to Vobiz.