WACM.in Logo
Back to API Overview
REST API

Verification API

OTP verification via WhatsApp/email and magic link verification with HMAC-SHA256 security.

Overview

The Verification API provides OTP-based and magic link verification for your users. It supports verification via WhatsApp and email channels, with fraud prevention and rate limiting built in.

Base URL

https://api.wacm.in

Authentication

The Verification API uses a custom API key authentication system with optional HMAC-SHA256 signature verification.

Required Headers

ParameterTypeRequiredDescription
X-Public-KeystringRequiredYour API public key (can also be sent as ?public_key= query param)
X-SignaturestringOptionalHMAC-SHA256 signature (base64-encoded). Optional but recommended.
X-TimestampstringOptionalUnix epoch timestamp (required when X-Signature is provided). Must be within 5 minutes of server time.

HMAC Signature Calculation

To compute the signature, construct a payload string and sign it with your API secret key:

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');
}

const timestamp = Math.floor(Date.now() / 1000).toString();
const signature = computeSignature(timestamp, 'POST', 'v1/verification/request', requestBody, secretKey);
HMAC Signature (PHP)
$timestamp = time();
$payload = $timestamp . '.' . $method . '.' . $path . '.' . $body;
$signature = base64_encode(hash_hmac('sha256', $payload, $secretKey, true));

Security Note

The timestamp tolerance is 300 seconds (5 minutes). Requests with timestamps older than 5 minutes will be rejected. Always include the X-Signature and X-Timestamp headers for production use.

Request Verification

Initiate a verification request. This sends an OTP via the specified channel (WhatsApp or email) and returns a request_id for subsequent verification.

POST
/v1/verification/request

Request Body

ParameterTypeRequiredDescription
profile_idstring (UUID)RequiredUUID of the verification profile to use
identifierstringRequiredPhone number or email to verify
channelstringRequired<code>whatsapp</code> or <code>email</code>
purposestringRequiredPurpose code (1-50 chars, e.g., "LOGIN", "SIGNUP")
trust_keystringOptionalOptional trust key (e.g., session ID, device ID)
captcha_tokenstringOptionalCAPTCHA verification token
silentbooleanOptionalSilent verification mode (no OTP sent)
Example Request
curl -X POST https://api.wacm.in/v1/verification/request \
     -H "X-Public-Key: YOUR_PUBLIC_KEY" \
     -H "X-Signature: COMPUTED_SIGNATURE" \
     -H "X-Timestamp: 1721000000" \
     -H "Content-Type: application/json" \
     -d '{
       "profile_id": "550e8400-e29b-41d4-a716-446655440000",
       "identifier": "+1234567890",
       "channel": "whatsapp",
       "purpose": "LOGIN"
     }'

Response

200 OK
{
  "request_id": "660e8400-e29b-41d4-a716-446655440001",
  "status": "pending",
  "expires_at": "2026-07-14T10:15:00.000000Z"
}

Note

The otp and magic_link fields are stripped from the response for security. The OTP is sent to the user via the specified channel.

Verify Code

Submit the OTP code received by the user to verify the request.

POST
/v1/verification/verify

Request Body

ParameterTypeRequiredDescription
request_idstring (UUID)RequiredThe request_id from the request verification step
codestringRequiredThe OTP code entered by the user
Example Request
curl -X POST https://api.wacm.in/v1/verification/verify \
     -H "X-Public-Key: YOUR_PUBLIC_KEY" \
     -H "Content-Type: application/json" \
     -d '{
       "request_id": "660e8400-e29b-41d4-a716-446655440001",
       "code": "123456"
     }'

Response

200 OK — Verified
{
  "verified": true,
  "request_id": "660e8400-e29b-41d4-a716-446655440001",
  "trust_key": "session_abc123",
  "identifier": "+1234567890",
  "channel": "whatsapp",
  "verified_at": "2026-07-14T10:05:00.000000Z"
}
200 OK — Failed
{
  "verified": false,
  "request_id": "660e8400-e29b-41d4-a716-446655440001"
}

Check Status

Check the current status of a verification request. Useful for polling verification status in real-time applications.

GET
/v1/verification/status/{request_id}

Example Request
curl -H "X-Public-Key: YOUR_PUBLIC_KEY" \
     https://api.wacm.in/v1/verification/status/660e8400-e29b-41d4-a716-446655440001

Response

200 OK — Pending
{
  "status": "pending"
}
200 OK — Verified
{
  "status": "verified",
  "trust_key": "session_abc123",
  "identifier": "+1234567890",
  "channel": "whatsapp",
  "verified_at": "2026-07-14T10:05:00.000000Z"
}

Resend Code

Resend the OTP code for a pending verification request. The request must not have expired.

POST
/v1/verification/resend

Request Body

ParameterTypeRequiredDescription
request_idstring (UUID)RequiredThe request_id to resend the code for
Example Request
curl -X POST https://api.wacm.in/v1/verification/resend \
     -H "X-Public-Key: YOUR_PUBLIC_KEY" \
     -H "Content-Type: application/json" \
     -d '{
       "request_id": "660e8400-e29b-41d4-a716-446655440001"
     }'

Response

200 OK
{
  "success": true,
  "message": "Resend initiated"
}

Magic Link Verification

Magic links allow users to verify by clicking a URL instead of entering an OTP. This endpoint is called when the user clicks the magic link in their email.

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

Rate Limit

This endpoint is rate-limited to 10 requests per minute (no API key required).

On success, returns an HTML page with a success message. On failure, returns an HTML page with an error. The magic link token is verified against the pending verification request.

Data Model

VerificationProfile

Central entity that configures verification behavior. Has many API keys, templates, webhooks, and whitelists.

ParameterTypeRequiredDescription
uuidstring (UUID)OptionalAuto-generated unique identifier (used as profile_id)
settings_jsonobjectOptionalProfile-specific settings (OTP length, expiry, etc.)

VerificationApiKey

Stores API key pairs for authentication. Each key is scoped to a company and profile.

ParameterTypeRequiredDescription
public_keystringRequiredPublic key used for authentication (X-Public-Key header)
secret_keystringRequiredSecret key used for HMAC signature computation
statusstringRequired<code>active</code> or <code>inactive</code>

VerificationRequest

Tracks individual verification attempts with status, expiry, and metadata.

ParameterTypeRequiredDescription
request_idstring (UUID)RequiredUnique identifier for this verification request
statusstringRequired<code>pending</code>, <code>verified</code>, <code>expired</code>, <code>failed</code>, <code>blocked</code>
expires_atdatetimeRequiredWhen the verification request expires
verified_atdatetimeOptionalWhen the code was successfully verified
metadata_jsonobjectOptionalRequest metadata (IP, user agent, etc.)

Error Responses

401Missing or invalid public key
422Validation failed — missing or invalid request fields
429Fraud prevention triggered — too many attempts
400Verification failed — wrong code, expired, or other error
404Verification request not found
Validation Error (422)
{
  "error": "Validation failed",
  "details": {
    "profile_id": ["The selected profile id is invalid."],
    "channel": ["The selected channel is invalid."]
  }
}
Fraud Prevention (429)
{
  "error": "Too many verification attempts. Please try again later."
}

Flowmaker Integration

The Verification API integrates with the AI Flow Builder through dedicated node types:

  • Request Verification — Initiate verification from within a flow
  • Verify Code — Verify a code submitted by the user
  • Verification Status — Check the status of a verification request

See the AI Flow Builder documentation for details on using verification nodes in flows.

Related Endpoints