Verification API Reference
Multi-channel identity verification (WhatsApp & Email), server-driven Zero-Release mobile configuration, 1-Click WhatsApp auto-login, and tamper-proof HMAC-SHA256 trust verification.
Verification API - LLM Context
LLM ReadyFeed complete OTP, 1-Click WhatsApp & Magic Link Verification API specs directly to your AI agent.
Planning your customer verification experience?
Explore WhatsApp and email OTP delivery, profile controls and the guided verification workflow before connecting the API.
Explore WhatsApp & Email OTP VerificationOverview
The Verification API provides multi-channel identity verification (WhatsApp and Email) with fraud prevention, rate limiting, and a server-driven Zero-Release mobile architecture.
Base URLs (Dual Prefix Supported)
https://app.wacm.in/api/v1/verification (Standard REST)https://app.wacm.in/v1/verification (Direct Alias)Authentication
All Verification API endpoints authenticate via your Public API Key (vpub_...). For server-to-server payload verification and a timestamp window, requests can include an HMAC-SHA256 signature and timestamp.
Headers
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| X-Public-Key | string | Required | Your public API key token (vpub_...). Can also be passed as query param ?public_key= |
| X-Timestamp | string | Optional | Unix epoch timestamp in seconds. Send together with X-Signature for signed requests. Validated only when both signature and timestamp are present; must be within 300s of server time. |
| X-Signature | string | Optional | Base64-encoded HMAC-SHA256 signature for payload verification. Send with X-Timestamp; requests within the timestamp window are not single-use. |
HMAC Signature Calculation
Construct a payload string of timestamp.method.path.body and sign it on your backend with your API secret key. Use the uppercase HTTP method, the path without its leading slash or query string, and the exact serialized body sent:
const crypto = require('crypto');
function computeSignature(timestamp, method, path, body, secretKey) {
const payload = `${timestamp}.${method}.${path}.${body}`;
return crypto
.createHmac('sha256', secretKey)
.update(payload)
.digest('base64');
}
// Serialize once and send these exact bytes as the HTTP request body.
const requestBody = JSON.stringify({ identifier: '+919876543210', channel: 'whatsapp' });
const timestamp = Math.floor(Date.now() / 1000).toString();
const signature = computeSignature(timestamp, 'POST', 'api/v1/verification/request', requestBody, secretKey);$timestamp = time();
$method = 'POST';
$path = 'api/v1/verification/request';
$body = json_encode(['identifier' => '+919876543210', 'channel' => 'whatsapp']);
$payload = $timestamp . '.' . $method . '.' . $path . '.' . $body;
$signature = base64_encode(hash_hmac('sha256', $payload, $secretKey, true));Signature Timestamp Window
When both signature and timestamp are present, timestamps more than 300 seconds (5 minutes) ahead of or behind server time are rejected. The current middleware does not enforce HMAC when either header is missing; send both for signed requests. Keep server clocks synchronized with NTP when using signed requests.
Quick Start & Integration Flow
Call GET /config to dynamically discover OTP rules, active WhatsApp bot number, and polling intervals without hardcoding.
Call POST /request with identifier. Receive request_id, otp_rules, and pre-built mobile_actions.
Submit OTP to POST /verify, or trigger 1-Click WhatsApp intent so the user verifies by simply sending a message.
App or backend polls GET /status/{request_id} to verify is_verified: true and retrieve trust_key for authenticated actions.
Mobile Configuration Discovery
Allows mobile applications (iOS, Android, Flutter, React Native) and web clients to dynamically discover verification profile settings, OTP length, active WhatsApp bot numbers, and recommended polling intervals at runtime. Prevents submitting new App Store / Play Store app updates when backend settings change.
/v1/verification/configDiscover verification profile config
Mandatory Headers
Required Authentication Header
| Parameter | Type | Required | Description |
|---|---|---|---|
| X-Public-Key | string | Required | Your API key public token (vpub_...). Or query parameter public_key. X-Secret-Key or Bearer alone is not accepted |
No query or request body parameters required.
curl -X GET https://app.wacm.in/api/v1/verification/config \
-H "X-Public-Key: vpub_your_public_key"Response (200 OK)
{
"status": "active",
"profile_id": "c1f7b8e2-8924-4f0e-b7d6-e24c519f3901",
"profile_name": "Default Verification Profile",
"channels": ["whatsapp", "email"],
"default_channel": "whatsapp",
"otp": {
"length": 6,
"type": "numeric",
"expiry_minutes": 5,
"expiry_seconds": 300,
"resend_cooldown_seconds": 30,
"max_attempts": 3
},
"whatsapp": {
"enabled": true,
"one_click_enabled": true,
"bot_phone": "15551234567"
},
"polling": {
"status_url_template": "/api/v1/verification/status/{request_id}",
"recommended_interval_ms": 2000,
"timeout_seconds": 120
}
}Request Verification
Initiates a verification request and dispatches an OTP or generates 1-Click WhatsApp intent URLs.
/v1/verification/requestRequest verification session
Mandatory Parameters
Mandatory Request Body
| Parameter | Type | Required | Description |
|---|---|---|---|
| identifier | string | Required | Destination phone number in E.164 format (e.g. +1234567890 or 919876543210) or valid email address (1-255 characters). |
Optional Parameters
Optional Request Body
| Parameter | Type | Required | Description |
|---|---|---|---|
| profile_id | string (UUID) | Optional | UUID of custom verification profile. Auto-resolved from authenticated API key or company default if omitted. |
| channel | string | Optional | Delivery channel: <code>whatsapp</code> or <code>email</code>. Defaults to <code>whatsapp</code>. |
| purpose | string | Optional | Context or reason tag (1–50 chars, e.g. "login", "checkout", "register"). Defaults to <code>default</code>. |
| trust_key | string | Optional | Optional previous client/device trust token to check for instant cached verification or bind with the new session. |
| captcha_token | string | Optional | Google reCAPTCHA token. Required only if your verification profile mandates CAPTCHA verification. |
| silent | boolean | Optional | If <code>true</code>, outbound OTP message is NOT dispatched. Ideal for WhatsApp 1-Click auto-login. Defaults to <code>false</code>. |
| ip_address | string (IP) | Optional | Client IP address used by fraud detection & velocity limiting. Automatically captured from connection if omitted. |
| user_agent | string | Optional | Client User-Agent string used for device auditing. Automatically captured if omitted. |
curl -X POST https://app.wacm.in/api/v1/verification/request \
-H "X-Public-Key: vpub_your_public_key" \
-H "Content-Type: application/json" \
-d '{
"identifier": "+1234567890",
"channel": "whatsapp",
"purpose": "login"
}'Response (Standard New Request)
{
"success": true,
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"profile_id": "c1f7b8e2-8924-4f0e-b7d6-e24c519f3901",
"otp_rules": {
"length": 6,
"type": "numeric",
"expiry_seconds": 300,
"resend_in_seconds": 30
},
"mobile_actions": {
"one_click_whatsapp": {
"enabled": true,
"intent_url": "whatsapp://send?phone=15551234567&text=Verify%20Request%3A+550e8400-e29b-41d4-a716-446655440000",
"universal_url": "https://wa.me/15551234567?text=Verify%20Request%3A+550e8400-e29b-41d4-a716-446655440000"
},
"polling_url": "/api/v1/verification/status/550e8400-e29b-41d4-a716-446655440000"
}
}Response (Cached / Skip Verification)
If the user has verified recently within your profile's trust caching window, the request immediately succeeds without issuing a new request ID or trust key. Polling and intent URLs are null; cached/reused flags may be omitted in other response branches:
{
"success": true,
"cached": true,
"verified": true,
"profile_id": "c1f7b8e2-8924-4f0e-b7d6-e24c519f3901",
"otp_rules": { "length": 6, "type": "numeric", "expiry_seconds": 300, "resend_in_seconds": 30 },
"mobile_actions": { "one_click_whatsapp": { "enabled": true, "intent_url": null, "universal_url": null }, "polling_url": null }
}Response (Reused / Session Resend)
When re-requesting verification for the same identifier while a session is still active, the server automatically reuses the existing code, extends the expiration window, increments the resends count, and returns "reused": true:
{
"success": true,
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"reused": true,
"profile_id": "c1f7b8e2-8924-4f0e-b7d6-e24c519f3901",
"otp_rules": {
"length": 6,
"type": "numeric",
"expiry_seconds": 300,
"resend_in_seconds": 30
},
"mobile_actions": {
"one_click_whatsapp": {
"enabled": true,
"intent_url": "whatsapp://send?phone=15551234567&text=Verify%20Request%3A+550e8400-e29b-41d4-a716-446655440000",
"universal_url": "https://wa.me/15551234567?text=Verify%20Request%3A+550e8400-e29b-41d4-a716-446655440000"
},
"polling_url": "/api/v1/verification/status/550e8400-e29b-41d4-a716-446655440000"
}
}WhatsApp 1-Click Verification (Auto-Login)
Eliminate manual OTP typing entirely. Using the server-driven response, your mobile app launches the native WhatsApp app pre-filled with the verification message.
1. Request with silent: true
Call /request with silent: true. No outbound OTP message is sent, saving messaging costs and keeping user focus in the app.
2. Launch WhatsApp Intent
On iOS and Android, open mobile_actions.one_click_whatsapp.intent_url (whatsapp://send?phone=...). On web browsers, open universal_url (https://wa.me/...). WhatsApp opens with the pre-filled verification code.
3. Auto-Verify via Webhook & Polling
When the user taps "Send" in WhatsApp, the WACM Verification Ingestor webhook intercepts the inbound message, verifies the request, and generates a trust_key. Your app polls polling_url; as soon as is_verified: true is returned, your app logs the user in immediately!
Validate Code
Validates an OTP submitted manually by the user in your frontend.
/v1/verification/verifyValidate OTP code
Mandatory Parameters
Mandatory Request Body
| Parameter | Type | Required | Description |
|---|---|---|---|
| request_id | string (UUID) | Required | The UUID session request_id received from the /request step. |
| code | string | Required | The OTP code entered by the user (1–20 characters, typically 4–8 digits). |
No optional parameters accepted.
curl -X POST https://app.wacm.in/api/v1/verification/verify \
-H "X-Public-Key: vpub_your_public_key" \
-H "Content-Type: application/json" \
-d '{
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"code": "123456"
}'Responses
{
"verified": true,
"trust_key": "trust_abc123xyz789..."
}{
"verified": false
}{
"error": "Maximum verification attempts reached. Try again in 30 minute(s)."
}Check Status & Retrieve Trust Key
Retrieves the current status of a verification request. Used by frontends polling during 1-Click WhatsApp flows, or by your backend server to retrieve the verified session details. This endpoint does not consume the trust key or create an application login session; the integrating backend is responsible for its authentication flow. The returned trust key is the caller-supplied value and may be null; it is not a newly issued login token.
/v1/verification/status/{request_id}Check status & retrieve trust key
Mandatory Path Parameters
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| request_id | string (UUID) | Required | The UUID of the verification request session to inspect or verify. |
No optional parameters accepted.
curl -X GET https://app.wacm.in/api/v1/verification/status/550e8400-e29b-41d4-a716-446655440000 \
-H "X-Public-Key: vpub_your_public_key"Response (Verified)
{
"status": "verified",
"is_verified": true,
"trust_key": "trust_abc123xyz789...",
"identifier": "+1234567890",
"channel": "whatsapp",
"verified_at": "2026-06-23T10:30:00+00:00"
}Response (Pending)
{
"status": "pending",
"is_verified": false
}Possible Status Values
verified: Verification completed successfully (containsis_verified: trueandtrust_key).pending: Awaiting OTP validation or 1-Click WhatsApp message (is_verified: false).expired: OTP or session expired before completion.failed: Maximum incorrect attempts reached.blocked: Blocked by fraud prevention rules.
Resend Code
Resends an OTP to the same identifier for an existing, pending verification request.
Tip (Recommended for Mobile Apps)
Instead of storing request_id and handling expired states manually, mobile applications can simply call POST /api/v1/verification/request again with the user's identifier. If an unexpired request exists, the server automatically reuses the same OTP code, extends the expiration window, increments the resend counter, re-dispatches the message, and returns "reused": true with the same request_id. If expired, it seamlessly generates a fresh request.
/v1/verification/resendResend OTP code
Mandatory Parameters
Mandatory Request Body
| Parameter | Type | Required | Description |
|---|---|---|---|
| request_id | string (UUID) | Required | The pending request_id to resend the code for. |
No optional parameters accepted.
curl -X POST https://app.wacm.in/api/v1/verification/resend \
-H "X-Public-Key: vpub_your_public_key" \
-H "Content-Type: application/json" \
-d '{
"request_id": "550e8400-e29b-41d4-a716-446655440000"
}'Response
{
"success": true,
"message": "Resend initiated"
}Magic Link Verification (Browser)
For email verification flows, users receive a clickable magic link. When the user clicks the link in their browser or email client, this public endpoint verifies the token and renders a browser confirmation page.
/v1/verification/magic/{request_id}/{token}Direct browser magic link (Public)
Mandatory Path Parameters
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| request_id | string (UUID) | Required | The UUID of the verification request session. |
| token | string | Required | The cryptographic single-use verification token sent in the magic link email. |
Public browser endpoint; no API key headers or optional parameters required.
Public Endpoint Note
No API key is required for this endpoint. It is rate-limited to 10 requests per minute per IP to prevent brute-force attacks and returns an HTML page (Content-Type: text/html). Client applications verify status asynchronously via /status/{request_id} or webhooks.
Webhook Integration
Instead of continuous polling, you can configure webhooks in your Verification Profile to receive real-time notifications when verification events occur.
Supported Events
verification.requested— Dispatched when a new verification request is createdverification.successful— Dispatched as soon as an OTP, 1-Click WhatsApp, or Magic Link is verifiedverification.failed— Dispatched when attempts exceed limits or fraud prevention is triggered
Webhook Payload Example
{
"event": "verification.successful",
"data": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"identifier": "+1234567890",
"channel": "whatsapp",
"purpose": "login",
"trust_key": "trust_abc123xyz789..."
},
"timestamp": "2026-06-23T10:30:00Z"
}Fraud Prevention & Security Features
The Verification Hub includes enterprise-grade fraud mitigation mechanisms:
- OTP Bombing Protection: Cooldown windows and per-identifier request throttling prevent abuse.
- IP Velocity Limiting: Enforces caps on unique phone numbers and emails initiated per IP within time windows.
- Disposable Email Filter: Blocks 10-minute and disposable email domains in real-time.
- reCAPTCHA Integration: Optional enforcement (disabled, always, or risk-based after failed attempts).
- IP & Country Allow/Blocklists: Restrict verification traffic to authorized regional markets.
Rate Limits
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| Authenticated API Endpoints | Endpoints | Required | 30 requests per minute per API key |
| Magic Link Browser Endpoint | Endpoints | Optional | 10 requests per minute per IP |
Data Model
VerificationProfile
Central entity configuring verification behavior, channels, OTP rules, security thresholds, and webhooks.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| uuid | string (UUID) | Required | Auto-generated unique identifier used as profile_id |
| name | string | Required | Profile display name |
| settings_json | object | Required | JSON settings defining OTP length, expiry, cooldowns, and fraud thresholds |
VerificationApiKey
API key pairs for authenticating client applications and backend systems.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| public_key | string | Required | Public identifier token passed in X-Public-Key header (vpub_...) |
| secret_key | string | Required | Secret key used for HMAC-SHA256 signature computation (vsec_...) |
| status | string | Required | active or inactive |
VerificationRequest
Tracks individual verification sessions and audit trails.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| request_id | string (UUID) | Required | Unique session identifier |
| status | string | Required | pending, verified, expired, failed, blocked |
| trust_key | string | Optional | Generated trust token upon successful verification |
| expires_at | datetime | Required | Session expiration timestamp |
| verified_at | datetime | Optional | Timestamp when verification completed |
Error Responses
{
"error": "Validation failed",
"details": {
"identifier": ["The identifier field is required."],
"channel": ["The selected channel is invalid."]
}
}{
"error": "Too many verification attempts. Please try again in 30 minute(s)."
}Flowmaker Integration
The Verification API integrates seamlessly with the WACM AI Flow Builder through dedicated flow nodes:
- Request Verification Node: Dispatches verification within automated customer journeys
- Verify Code Node: Validates user input received in conversational flows
- Check Status Node: Conditions subsequent branch logic based on verified trust status
Related Documentation
- WhatsApp Business API — Direct WhatsApp messaging and template dispatches
- AI Flow Builder — Build visual conversational journeys with built-in verification
- eCommerce Storefront API — Verify customer identities at checkout