Base URL: https://api.shernova.com · Errors: { error, message, error_code, doc_url, request_id } · OpenAPI Swagger UI is disabled on production (/docs returns 404); use this reference or your local dev server.
Authentication
| Header | Used for |
|---|---|
| Authorization: Bearer {jwt} | Dashboard & org routes |
| Authorization: Bearer sk_live_… | Production server verification API |
| Authorization: Bearer sk_test_… | Test server verification API |
| Authorization: Bearer {sdk_jwt} | Mobile SDK verification calls |
| Authorization: Bearer pk_live_… / pk_test_… | POST /v1/sdk/token only |
| X-Shernova-Organization-Id | Org-scoped dashboard routes |
| X-Shernova-Gateway-Token | Gateway device routes only |
Health
GET /health/live
Purpose: Liveness probe. Auth: None.
GET /health/ready
Purpose: Readiness (DB + Redis). Auth: None.
Auth
POST /v1/auth/register
Purpose: Create developer account. Auth: None.
{ "email": "dev@company.com", "password": "secure-password" }POST /v1/auth/login
{ "email": "dev@company.com", "password": "secure-password" }POST /v1/auth/refresh
{ "refresh_token": "…" }GET /v1/auth/me
Purpose: Current user profile. Auth: JWT.
Applications
GET /v1/apps
Purpose: List organization apps. Auth: JWT + APPS_READ.
POST /v1/apps
{ "name": "My App", "webhook_url": "https://example.com/webhooks/shernova" }PATCH /v1/apps/:id
{ "name": "Updated name", "webhook_url": "https://…", "is_active": true }POST /v1/apps/:id/test-webhook
{ "webhook_url": "https://example.com/webhooks/shernova" }POST /v1/apps/:id/rotate-api-key · rotate-webhook-secret
{ "reason": "Scheduled rotation" }Verifications
Never call this from the browser
sk_live_… and sk_test_… are server secrets. Proxy create/status/cancel through your backend. See Website Integration for complete Node.js, PHP, and Python flows.
POST /v1/verifications
Purpose: Start verification session. Auth: API key (sk_live_ or SDK JWT).
curl -X POST https://api.shernova.com/v1/verifications \
-H "Authorization: Bearer sk_live_…" \
-H "Content-Type: application/json" \
-d '{"phone_number":"+201012345678","client_request_id":"my-idempotency-key-12345678"}'{
"session_id": "uuid",
"status": "waiting",
"gateway_phone_number": "+201140774187",
"qr_code_data": "tel:+201140774187",
"environment": "live",
"method": "missed_call",
"expires_at": "2026-07-21T12:00:00.000Z"
}Optional header: Idempotency-Key (8-128 chars). Test-key sessions use real gateways and consume credits - same flow as live.
If no gateway line is free, the session is created as queued: gateway_phone_number is null and queue_reason is one of none_online, country_unavailable, all_busy. Keep polling GET /v1/verifications/:id until status becomes waiting (a gateway line was assigned) - only then place the call. Treat gateway_phone_number as nullable and read it again on every poll.
qr_code_data is the same gateway number as a tel: URI. Render it as a QR code while waiting so desktop users can scan it with the phone that will place the call instead of typing the number. It is null while queued and after the session leaves waiting.
GET /v1/verifications/:id
Purpose: Poll session status (created → queued → waiting → terminal). Auth: API key.
DELETE /v1/verifications/:id
Purpose: Cancel a waiting or queued session (releases credit hold). Auth: API key.
GET /v1/dashboard/sessions
Purpose: List org verification sessions in dashboard. Auth: JWT + SESSIONS_READ.
SDK Token
POST /v1/sdk/token
Purpose: Exchange publishable key for short-lived JWT. Auth: Bearer pk_live_…
{
"package_name": "com.yourcompany.app",
"sha256": "64-char-hex",
"nonce": "random-min-8-chars"
}{
"access_token": "eyJ…",
"token_type": "Bearer",
"expires_in": 180,
"app_id": "uuid",
"available_credits": 100,
"ui": { "waiting_title": "…", "waiting_body": "…" }
}Test keys (pk_test_ / sk_test_)
Test keys create sessions against real online gateways. Complete by placing a missed call to gateway_phone_number (once status is waiting; it is null while queued) from the user's phone. Credits are held and captured like live sessions.
Receipts
POST /v1/verifications/:id/receipt
Purpose: Issue signed JWT receipt for a verified session. Auth: API key (sk_* or SDK JWT).
POST /v1/receipts/verify
Purpose: Verify receipt JWT server-side. Auth: API key. Replay returns 409 receipt_already_used (SH_014).
{ "receipt": "eyJ…" }Billing (Developer)
GET /v1/apps/:id/billing
Purpose: Credit balance and plan info. Auth: JWT + APPS_READ.
GET /v1/apps/:id/billing/ledger
Purpose: Credit ledger entries. Auth: JWT + APPS_READ.
POST /v1/apps/:id/android-signatures
{ "package_name": "com.app", "sha256": "…", "label": "Release" }Organizations
Routes: POST/GET /v1/organizations, GET/PATCH /v1/organizations/current, members, invitations, analytics. Auth: JWT + org permissions.
Admin (Platform)
Routes under /v1/admin/* for platform operators: users, organizations, gateways, sessions, webhooks, audit, billing management. Auth: JWT + platform permissions.
Gateway (Internal)
POST /v1/gateway/ring, /v1/gateway/heartbeat, GET /v1/gateway/health. Used by Shernova gateway Android app - not for integrators.
Session Status Values
created, queued, waiting, verified, rejected, expired, failed, cancelled, completed
