Sinch Verification API
Overview
The Sinch Verification API verifies phone numbers through SMS OTP, Flashcall (missed call CLI), Phone Call (spoken OTP), Data (carrier-level), and WhatsApp OTP. Used for registration, 2FA, and number ownership confirmation.
Base URL: https://verification.api.sinch.com
URL path prefix:
Auth: Application Key + Secret (NOT project-level OAuth2 — see
Authentication Guide)
Agent Instructions
Before generating code, you MUST ask the user:
- Which verification method? — , , , , or
- SDK or direct HTTP? — If SDK, which language?
Do not assume defaults or skip these questions. Wait for answers before generating code.
For SDK syntax, fetch the appropriate reference:
For direct HTTP, use the
API Reference (Markdown) for request/response schemas.
Getting Started
Authentication
See sinch-authentication skill for dashboard setup.
The Verification API uses Application Key + Application Secret (from your Sinch dashboard app), not project-level OAuth2. Three auth methods are supported:
| Method | Use for |
|---|
| Application Signed Request | Secure authentication method for production traffic |
| Basic Auth | Simple method for prototyping and trying out API calls |
| Public Auth | Insecure environments (end user's device). Android/iOS SDK only, requires callback webhook |
Minimum auth level is configurable in the Sinch Dashboard — requests below that level are rejected. See the
Authentication Guide for signing details.
SDK Setup
| Language | Package | Install |
|---|
| Node.js | or | npm install @sinch/sdk-core
|
| Python | | |
| Java | com.sinch.sdk:sinch-sdk-java
| Maven dependency |
| .NET | | |
All SDKs initialize with
+
(not project credentials).
Canonical Example — Start SMS Verification
bash
# Uses Basic Auth (-u) for simplicity. Use Application Signed Requests in production.
curl -X POST https://verification.api.sinch.com/verification/v1/verifications \
-H 'Content-Type: application/json' \
-u YOUR_APPLICATION_KEY:YOUR_APPLICATION_SECRET \
-d '{
"identity": { "type": "number", "endpoint": "+12025550134" },
"method": "sms"
}'
Response includes
(verification ID),
,
, and
with localized URLs for status/report actions.
Key Concepts
Verification Methods
| Method | Value | Behavior |
|---|
| SMS | | Sends OTP via SMS. User enters code. |
| FlashCall | | Missed call — caller ID is the OTP. Auto-intercepted on Android; manual entry on iOS/JS. |
| Phone Call | | PSTN call dictates an OTP code. User enters the code into the app (same flow as SMS). |
| Data | | Carrier-level verification via mobile data. No user interaction. Requires account manager to enable. |
| WhatsApp | | Sends OTP via WhatsApp message. User enters code. |
Core Model
- Identity: Always
{ "type": "number", "endpoint": "+E164_NUMBER" }
- Verification ID: Returned on start. Used to report code or query status.
- Reference: Optional unique tracking string in start request. Queryable via status endpoint.
- Statuses: | | | | |
- Failure reasons (most common): , , , , . Full list in the API Reference.
API Endpoints
All endpoints documented in the
Verification API Reference.
Start Verification
POST /verification/v1/verifications
Set
to
,
,
,
, or
. Optional fields:
- — unique tracking string, passed to all events
- — arbitrary text (max 4096 chars), passed to all events
- header — controls SMS language (default )
Method-specific options (backend-originated signed requests only):
,
,
,
. See the
API Reference for full schemas.
Report Verification
Report by identity:
PUT /verification/v1/verifications/number/{endpoint}
Report by ID:
PUT /verification/v1/verifications/id/{id}
Body includes
and a method-specific object with the user's input:
- SMS / Phone Call / WhatsApp:
{ "method": "sms", "sms": { "code": "1234" } }
(replace method name + key accordingly)
- FlashCall:
{ "method": "flashcall", "flashCall": { "cli": "+46000000000" } }
— the is the full international caller ID from the incoming missed call
Get Verification Status
By ID:
GET /verification/v1/verifications/id/{id}
By method + number:
GET /verification/v1/verifications/{method}/number/{endpoint}
By reference:
GET /verification/v1/verifications/reference/{reference}
Note: The by-identity endpoint requires
in the path — it is NOT
/verifications/number/{endpoint}
.
Common Patterns
Standard Verification Flow
- Start —
POST /verification/v1/verifications
with identity + method → receive verification
- Report — User receives code/call →
PUT /verification/v1/verifications/id/{id}
with the code/CLI
- Check status —
GET /verification/v1/verifications/id/{id}
→ confirm
If the code expires or verification fails, you cannot re-report — start a new verification.
Webhooks (Callbacks)
For production flows, configure a callback URL in the Sinch Dashboard. The API sends:
- VerificationRequestEvent — fired when a verification starts. Respond with or to approve/reject.
- VerificationResultEvent — fired when a verification completes (success or failure). Use for logging, analytics, or triggering downstream actions.
Callbacks are signed — verify signatures using
Callback Signing.
Gotchas and Best Practices
- Auth is Application Key + Secret, not OAuth2. Do not use project-level credentials.
- Use Application Signed Requests in production. Application auth protects integrity of a request
- Base64-decode the secret before signing. The dashboard value is base64-encoded.
- FlashCall auto-intercepts on Android only. iOS/JS users must manually enter the incoming number. Android SDK is required to intercept calls.
- Method availability varies by country. SMS is the most widely available.
- Codes expire. Configurable via . Start a new verification if expired — you cannot re-report on a completed/expired verification.
- Report by ID is more precise than reporting by phone number.
- Rate limit: avoid rapid re-verification of the same number. Implement backoff.
- Data verification requires account manager and mobile data (not Wi-Fi).
- SMS language may be overridden by carrier compliance (e.g., US shortcode requirements).
Links