Skip to main content

Verify API

One-time-password (OTP) issuance and validation across SMS, voice (TTS), email, and WhatsApp. Two patterns:
  • Direct — issue an OTP to a phone / email; validate the code the user enters.
  • Profile-based — define a verify profile (channel, code length, expiration, locale, sender), then reference it by name from your app. Lets you tune behavior without redeploying.
Base path: /api/v1/verify Authentication: API key (X-API-Key) or session JWT.

Send & check

Bulk send

POST /api/v1/verify/bulk fans an OTP out to up to 1000 recipients that share one channel and (optionally) one verify profile_id / template_variables bag — built for login surges and password-reset campaigns. Each recipient flows through the same per-recipient pipeline as POST /verify/send (E.164 / email validation, per-recipient rate limit, fraud velocity, wallet deduct, MessageRouter dispatch), so no new outbound path is introduced. Recipients are de-duplicated (first-occurrence order preserved) and dispatched with a bounded-parallel worker pool; one recipient’s failure never aborts the batch. This endpoint is rate-limited to 2 requests / minute per tenant (each call can mint up to 1000 OTPs) — operators can raise it with a per-org override. Request body Response — a single envelope with batch totals plus one row per recipient (returned in submission order):
Each result row is one of:
  • sent{ recipient, status: "sent", verification_id, channel }
  • failed{ recipient, status: "failed", error: { code, message } }
Status codes — the HTTP status reflects the batch outcome so SDKs can branch on response.ok:

Verifications

GET /api/v1/verify/analytics aggregates verifications over a rolling look-back window. Pass an optional window_days query parameter to size the window; the applied value is echoed back in the response. Query parameters Response GET /api/v1/verify/conversion-anomaly is the Verify Fraud Shield discovery signal for artificially-inflated traffic (AIT / SMS-pumping). It scores each destination prefix by its OTP completion rate (verified ÷ sent) over an optional window_days look-back (1–90, default 30): destinations converting far below the tenant baseline against a material send volume are flagged, and the response headlines an estimated carrier spend-at-risk (USD). The payload is { window_days, total_sent, total_verified, baseline_conversion_rate, flagged_destinations, estimated_spend_at_risk_usd, destinations[] }, where each destination carries { prefix, sent, verified, conversion_rate, score, band, anomaly, estimated_spend_at_risk_usd }. Read-only and tenant-scoped.

Profiles

Configs (alias of profiles)

/api/v1/verify/configs* is a frontend-facing alias of /profiles* — same controller, identical payloads and behaviour. It exists because the dashboard consumes the /configs naming; either path may be used interchangeably.

Channels

POST /api/v1/verify/send accepts channel: sms, whatsapp, voice, email, viber, telegram, rcs, flashcall (delivery channels) plus the non-delivery / factor channels silent, sna, totp, push, magic_link, backup_code. rcs delivers the code through your tenant’s verified RCS Business Messaging agent (branded logo + checkmark, higher trust than plain SMS), failing closed with 503 PROVIDER_NOT_WIRED when no RCS provider is registered — so it slots cleanly into a fallback chain such as rcs → sms. flashcall delivers the code as the trailing digits of a missed call’s caller ID; the recipient submits those digits to /check. sna (Silent Network Authentication) verifies SIM possession through the CAMARA broker when you pass a device-bound device_token, returning status: "verified" with no OTP; without one it fails closed with 503 PROVIDER_NOT_WIRED. totp/push/backup_code short-circuit and steer you to the matching factor endpoints below. See the Verify overview for the full channel reference.

MFA factors

Possession-of-secret and phishing-resistant factors for end-tenant users. These factors carry no carrier delivery and no wallet deduct. Create/verify/delete require the verify:write scope.
These factors are API-only by design — there is no dashboard screen for them. TOTP, backup codes, passkeys (WebAuthn / FIDO2), and push are enrolled, verified, and revoked from inside your own application, where your end user is present to scan a QR code, complete a WebAuthn ceremony, or approve a push prompt on their device. Drive them straight from the endpoints below (or the SDK). The Verify dashboard covers OTP send/check, profiles, and analytics; the 2FA control under Settings → Security protects your Orbit login and is separate from these end-user factors.

TOTP (authenticator app)

Backup codes

Verify Push

Passkeys (WebAuthn / FIDO2)

Example — send and validate an SMS OTP

On a matching code the check endpoint returns 200 with { data: { verification_id: "vrf_3f1c0b2a8e4d4f7a9c2b1e6d5a4c3b2a", status: "approved" } }. Failures are not 200 bodies — they surface in the error envelope, where details.attempts_remaining counts the tries left: Codes have a small fixed number of attempts (default 3) before they’re exhausted. The check status enum is ["approved", "failed", "expired"]failed and expired only ever appear inside the error envelope (or via GET /api/v1/verify/{id}), never as a 200 body. See Verify without an SDK for the full status model.

See also