Skip to main content
Voice Authentication is an outbound call-to-approve primitive. Your backend asks Wave to verify someone; Wave calls that number, plays a short bilingual prompt describing what’s being authorized, captures the keypress, and returns a trustworthy, machine-readable verdict over a signed webhook (and a status API). It’s the voice equivalent of a push-to-approve / OTP step — a security factor, not a menu-tree IVR. Because the outcome gates access, it is fail-closed by design: only an explicit approval grants, and a machine/voicemail answer can never approve.
This is an outbound, API-triggered flow (Wave calls the user). It is distinct from IVR Menus (a caller dials you). Voice Authentication is gated — ask your Wave contact to enable it for your account.

Authentication & tiers

Every /v1/voice-auth endpoint needs a production API key (sk_live_) with the voice_auth:write scope (or voice_auth:read for status). Sandbox keys can’t place real authentication calls.

Create a challenge

201 returns the challenge id and (for number_match) the digits to display:

The verdict — fail closed

A challenge resolves to exactly one terminal state:
Only approved and declined are affirmative user decisions. Treat every other state as a non-grant and fail closed. Always confirm the verdict via the status API (below) before honoring an approval — defense in depth.

Answering-machine detection (AMD)

Before any prompt, Wave classifies who answered. A machine or voicemail answer resolves to machine_detected and the approval prompt is never played — so a voicemail can never capture a keypress or leave a stray approval. This is enforced, not best-effort.

High-assurance number matching

For high-value actions (payments, admin changes), set assurance: "number_match". The 201 response includes match_digits (e.g. "47") — display them to your user. The call then asks the callee to key those exact digits to approve. A wrong entry never approves — this defeats “just press 1” MFA-fatigue and accidental approvals.

The result webhook

On a terminal state Wave sends a signed voice_auth.completed event to your project’s webhook endpoint:
Verify every delivery:
  • X-Wave-Signaturesha256=…, an HMAC-SHA256 of the raw body with your endpoint’s signing secret. Reject a mismatch.
  • X-Wave-Timestamp — unix seconds; reject deliveries older than your window (e.g. 5 minutes).
  • X-Wave-Event-Id — stable across retries; dedupe on it.
The webhook is a notification — reconfirm via the status API before granting.

Poll status

Returns the current state, attempts, amd_result, timestamps, and (once terminal) the decision. Scoped to your organization only.

Idempotency, rate limits & abuse controls

  • Idempotency — send an Idempotency-Key; a retry with the same key returns the same challenge and never places a second call.
  • Per-number & per-originator limits — Wave caps challenges to a single number and per API key, and blocks known-abusive numbers/prefixes, to prevent voice-bombing and toll fraud. Over a limit → 429.

Errors