Documentation

Architecture

End-to-end flow from your application through verification and webhooks.

System Overview

Shernova connects your application, mobile SDK or server API, billing credits, physical gateway phones, and optional webhooks into one verification pipeline.

Components

ComponentRole
Developer DashboardManage apps, keys, billing, sessions, team
REST APICreate and query verification sessions
Flutter SDKToken exchange + UI + polling
Billing EngineHold → Capture/Release per session
Gateway Android AppReceives calls, posts ring events
Webhook DeliveryPOST signed events to your HTTPS endpoint

Session Lifecycle

Authentication Layers

  • Dashboard JWT — browser sessions for dashboard and org management
  • Secret key (sk_live_ / sk_test_) — server-side verification API; test keys use real gateways and consume credits
  • Publishable key (pk_live_ / pk_test_) — SDK token exchange only
  • SDK JWT — short-lived (~180s), used like secret key for verifications
  • Gateway tokenX-Shernova-Gateway-Token for gateway devices only

Verification Data Flow

  1. App requests verification with phone number in E.164 format
  2. API validates billing (active, not frozen, credits available) and holds 1 credit
  3. API selects an online gateway and returns gateway_phone_number
  4. User places missed call from the same phone number
  5. Gateway app sends ring event; API matches caller tail to session
  6. Session status becomes verified; credit is captured; webhook is queued

Default session TTL is 300 seconds. Gateway must heartbeat within 120 seconds to stay online.

Test keys vs live keys

  • Test keys (sk_test_, pk_test_) use real Android gateways and consume credits
  • Live keys (sk_live_, pk_live_) — same verification flow for production users
  • Dashboard — Sessions page shows key type (test / live) and session status

Receipts (server proof)

  1. After verified, issue receipt: POST /v1/verifications/:id/receipt
  2. Send JWT receipt to your backend
  3. Verify once server-side: POST /v1/receipts/verify with sk_* — replay returns SH_014