WACM.in Logo
Back to API Overview
Verification Module v1.0

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 Ready

Feed complete OTP, 1-Click WhatsApp & Magic Link Verification API specs directly to your AI agent.

Download .mdOpenAPI 3.1
Machine-Readable Feeds:/llms.txt /llms-full.txt

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 Verification

Overview

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

ParameterTypeRequiredDescription
X-Public-KeystringRequiredYour public API key token (vpub_...). Can also be passed as query param ?public_key=
X-TimestampstringOptionalUnix 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-SignaturestringOptionalBase64-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:

HMAC Signature (Node.js)
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);
HMAC Signature (PHP)
$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

1Discover Config

Call GET /config to dynamically discover OTP rules, active WhatsApp bot number, and polling intervals without hardcoding.

2Request Verification

Call POST /request with identifier. Receive request_id, otp_rules, and pre-built mobile_actions.

3Verify Code / 1-Click

Submit OTP to POST /verify, or trigger 1-Click WhatsApp intent so the user verifies by simply sending a message.

4Status & Retrieve Trust Key

App or backend polls GET /status/{request_id} to verify is_verified: true and retrieve trust_key for authenticated actions.

Mobile Configuration Discovery

Zero-Release Architecture

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.

GET
/v1/verification/config

Discover verification profile config

Mandatory Headers

Required Authentication Header

ParameterTypeRequiredDescription
X-Public-KeystringRequiredYour 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.

Example Request
curl -X GET https://app.wacm.in/api/v1/verification/config \
     -H "X-Public-Key: vpub_your_public_key"

Response (200 OK)

200 OK — Config Payload
{
  "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.

POST
/v1/verification/request

Request verification session

Mandatory Parameters

Mandatory Request Body

ParameterTypeRequiredDescription
identifierstringRequiredDestination phone number in E.164 format (e.g. +1234567890 or 919876543210) or valid email address (1-255 characters).

Optional Parameters

Optional Request Body

ParameterTypeRequiredDescription
profile_idstring (UUID)OptionalUUID of custom verification profile. Auto-resolved from authenticated API key or company default if omitted.
channelstringOptionalDelivery channel: <code>whatsapp</code> or <code>email</code>. Defaults to <code>whatsapp</code>.
purposestringOptionalContext or reason tag (1–50 chars, e.g. "login", "checkout", "register"). Defaults to <code>default</code>.
trust_keystringOptionalOptional previous client/device trust token to check for instant cached verification or bind with the new session.
captcha_tokenstringOptionalGoogle reCAPTCHA token. Required only if your verification profile mandates CAPTCHA verification.
silentbooleanOptionalIf <code>true</code>, outbound OTP message is NOT dispatched. Ideal for WhatsApp 1-Click auto-login. Defaults to <code>false</code>.
ip_addressstring (IP)OptionalClient IP address used by fraud detection & velocity limiting. Automatically captured from connection if omitted.
user_agentstringOptionalClient User-Agent string used for device auditing. Automatically captured if omitted.
Example Request (Standard OTP)
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)

200 OK — Verification Dispatched
{
  "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:

200 OK — Instant Cached Verification
{
  "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:

200 OK — Reused Active Session
{
  "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)

Zero Typing Friction

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.

POST
/v1/verification/verify

Validate OTP code

Mandatory Parameters

Mandatory Request Body

ParameterTypeRequiredDescription
request_idstring (UUID)RequiredThe UUID session request_id received from the /request step.
codestringRequiredThe OTP code entered by the user (1–20 characters, typically 4–8 digits).

No optional parameters accepted.

Example Request
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

200 OK — Verified
{
  "verified": true,
  "trust_key": "trust_abc123xyz789..."
}
200 OK — Invalid Code
{
  "verified": false
}
400 Bad Request — Max Attempts Reached / Expired
{
  "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.

GET
/v1/verification/status/{request_id}

Check status & retrieve trust key

Mandatory Path Parameters

Path Parameters

ParameterTypeRequiredDescription
request_idstring (UUID)RequiredThe UUID of the verification request session to inspect or verify.

No optional parameters accepted.

Example Request
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)

200 OK — 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)

200 OK — Pending
{
  "status": "pending",
  "is_verified": false
}

Possible Status Values

  • verified: Verification completed successfully (contains is_verified: true and trust_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.

POST
/v1/verification/resend

Resend OTP code

Mandatory Parameters

Mandatory Request Body

ParameterTypeRequiredDescription
request_idstring (UUID)RequiredThe pending request_id to resend the code for.

No optional parameters accepted.

Example Request
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

200 OK
{
  "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.

GET
/v1/verification/magic/{request_id}/{token}

Direct browser magic link (Public)

Mandatory Path Parameters

Path Parameters

ParameterTypeRequiredDescription
request_idstring (UUID)RequiredThe UUID of the verification request session.
tokenstringRequiredThe 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 created
  • verification.successful — Dispatched as soon as an OTP, 1-Click WhatsApp, or Magic Link is verified
  • verification.failed — Dispatched when attempts exceed limits or fraud prevention is triggered

Webhook Payload Example

Webhook Payload (verification.successful)
{
  "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

ParameterTypeRequiredDescription
Authenticated API EndpointsEndpointsRequired30 requests per minute per API key
Magic Link Browser EndpointEndpointsOptional10 requests per minute per IP

Data Model

VerificationProfile

Central entity configuring verification behavior, channels, OTP rules, security thresholds, and webhooks.

Parameters

ParameterTypeRequiredDescription
uuidstring (UUID)RequiredAuto-generated unique identifier used as profile_id
namestringRequiredProfile display name
settings_jsonobjectRequiredJSON settings defining OTP length, expiry, cooldowns, and fraud thresholds

VerificationApiKey

API key pairs for authenticating client applications and backend systems.

Parameters

ParameterTypeRequiredDescription
public_keystringRequiredPublic identifier token passed in X-Public-Key header (vpub_...)
secret_keystringRequiredSecret key used for HMAC-SHA256 signature computation (vsec_...)
statusstringRequiredactive or inactive

VerificationRequest

Tracks individual verification sessions and audit trails.

Parameters

ParameterTypeRequiredDescription
request_idstring (UUID)RequiredUnique session identifier
statusstringRequiredpending, verified, expired, failed, blocked
trust_keystringOptionalGenerated trust token upon successful verification
expires_atdatetimeRequiredSession expiration timestamp
verified_atdatetimeOptionalTimestamp when verification completed

Error Responses

401Missing or invalid API key / signature mismatch
422Validation error — invalid parameters
429Fraud prevention triggered — OTP bombing or velocity limits exceeded
400Bad Request — expired session or verification failed
404Verification request not found
422 Validation Error
{
  "error": "Validation failed",
  "details": {
    "identifier": ["The identifier field is required."],
    "channel": ["The selected channel is invalid."]
  }
}
429 Fraud Prevention
{
  "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