Skip to main content

KBA caller verification

An inbound call reaches your contact center with a phone number — nothing more. Before an agent discusses account details, takes a payment, or changes anything on the account, someone has to answer: is this caller who the number’s contact profile says they are? Knowledge-based authentication (KBA) answers it by challenging the caller with questions drawn from facts already on file for the call’s linked contact — email, the last 4 digits of the phone number, the full name, the company name. Orbit ships KBA as a voice-pillar primitive, alongside the OTP-code model documented in Verification session lifecycle and enrolled-voiceprint matching in Voice biometrics. This page is the concept-level map: what a challenge is, which endpoints drive it, how the attempt budget behaves, and where the audit ledger lives.

Why KBA exists

OTP verification proves someone controls a phone or email you can reach out-of-band — it dispatches a code on a second channel. Voice biometrics prove the caller sounds like an enrolled voiceprint. Neither fits the classic contact-center moment: the caller is already on the line, the agent needs a check now, and voiceprint enrollment or an SMS-capable number isn’t assumed. KBA fills that gap with evidence your CRM already holds. The agent reads two or three prompts aloud — “Can you confirm the email we have on file?”, “Can you confirm the last 4 digits of the phone number?”, “Can you confirm the full name on this account?”, “Can you confirm the company name?” — and submits the caller’s spoken answers. No new PII is collected: the expected answers come from the existing contact record linked to the call, and answers are never logged or audited verbatim, only per-factor pass/fail outcomes.

The endpoint surface under /voice/kba

Two resource shapes sit under the same prefix. Pick the one that matches your agent workflow — both end in the same verified/not-verified gate. Stateful per-call ledger. Useful when you want every start, attempt, and lockout readable on the call record itself: Stateless signed-token pair. Useful when you’d rather round-trip a challenge token than address a call id:

Factor selection and question count

A challenge draws 2–3 questions from the on-file profile — a default of three where the data supports it. Factors that are empty on the contact record are skipped, and a contact with fewer than two verifiable fields can’t be meaningfully challenged at all: start returns a 422 KBA_INSUFFICIENT_PROFILE_DATA, and the call needs an alternate verification method (agent judgement, a callback, an OTP send). The stateless pair defaults to date-of-birth and ZIP factors when your tenant configuration doesn’t pin a factor list.

The bounded attempt budget and lockout

Every mismatched submission burns one attempt against a bounded budget — three on the stateful ledger before the session flips failed; a configurable windowed count on the stateless pair (default five per contact). This counter is the brute-force guard on an identity gate, so submissions serialize correctly under concurrency: parallel guesses each consume their own attempt and trip the lockout on schedule rather than sharing a counter value. Exhaustion is terminal. On the stateful ledger the session sits in failed until you deliberately pass restart: true to start a fresh challenge — a stray retry can’t route around the lockout. On the stateless pair, repeated challenge issuance counts against the same per-contact budget, so cycling /challenge doesn’t reset it either.

Verified sessions, and what gates on them

A fully-matched submission opens a verified session. Reads compute the effective status at request time — a stored verified flag past its expiry reports as expired, never as verified — so stale rows can’t silently gate later actions. In the stateless pair the verify response hands back a session_token, and /session/check is the read-only gate payment, PII-disclosure, and account-change tools call before they proceed.

The migration-free ledger

The stateful session lives on the call record — in the call log’s metadata under kba_verification — rather than in a new table. This is Orbit’s extend-metadata pattern (the same one lightweight annotations like MCID use): a read-model cache on the existing call row, so the feature ships with no schema migration and everything stays inside your tenant schema. The cache-cell shape holds the session id, status, factor list, attempt counters, and the verified/failed timestamps.

Answers stay out of the record

Only outcomes are persisted or audited: which factor keys were checked, and the pass/fail result for each. Spoken answer values are never written to logs or the audit trail — KBA is a tenant-owned control over your call data, not a capture of new caller PII.

Outbound signalling is never involved

KBA is read-and-compare over data already on file plus annotation of the call record. It originates no outbound call or message and touches no carrier leg, so all outbound traffic continues to exit only through the Devotel softswitch — the verification flow itself never wires a signaling path of its own.

Challenge → verify with curl

The stateful ledger, end to end:
The response carries the session_id and the question set (factor + prompt pairs — the caller-facing text the agent reads aloud).
A verified status comes back when every submitted factor matches; a mismatch returns per-factor results and the remaining attempt count, and the session locks when the budget runs out.
Sensitive actions (payments, PII disclosure, account changes) can require this gate before they accept the call — expect a 403 KBA_VERIFICATION_REQUIRED until the session verifies.

Where the how-to lives