Skip to guide
WhatsOS

BUILD WITH WHATSOS

One OTP API.
Your way to build.

Add WhatsApp phone verification to your application, command line or WordPress site. Get working clients, a WordPress plugin and a clear contract for your coding tools.

Choose who generates and verifies the OTP

WhatsOS-generated OTP: use the verification flow below. Send your own OTP: your software generates and verifies the code; WhatsOS delivers it using your existing API key and template.

Read the supplied-code delivery API guide

THE INTEGRATION CONTRACT

Request. Verify. Complete once.

Start with a test project and a scoped API key in your OTP workspace. Test delivery is simulated and uses code 123456. Keep the key in your server's secret store.

  1. Your application creates a server-side action session bound to the intended phone, purpose and environment.
  2. Your backend requests an OTP and stores the returned verification_id in that session.
  3. The user enters the code. Your backend checks it against the stored ID.
  4. Require verified: true and status: verified, then complete the matching action once.
The browser calls your backend. Your backend calls WhatsOS.

Keys, session binding and approval decisions belong on your server. Message delivery, browser events and sandbox results cannot approve real customer actions.

Base URL: https://whatsos.com/api/v1/otp
MethodEndpointScope
POST/verificationsotp:send
POST/verifications/{id}/checkotp:verify
POST/verifications/{id}/resendotp:send
POST/verifications/{id}/cancelotp:cancel
GET/verifications/{id}otp:read

POST requests use Bearer authentication, JSON and an Idempotency-Key. Persist a unique key before each operation. On a timeout or uncertain result, retry the exact body with the same key. After a definitive rejection such as a rate limit, wait as directed, then use a new key for a new attempt.

Resend replaces the challenge after its cooldown: store the new verification ID. Codes last five minutes. A replayed successful check must never repeat your business action. See errors and retry handling.

01 / TERMINAL

Use your existing CLI workflow.

Download and extract the starter kit. Node.js 18+ is required; there are no npm dependencies. Set WHATSOS_OTP_KEY securely in the process environment. The CLI reads it automatically.

Bash · sandbox walkthrough
# Set WHATSOS_OTP_KEY securely in this backend shell first.
# Extract the starter ZIP; keep the CLI and Node client together.
node whatsos-otp-cli.mjs send \
  --to +12025550123 --purpose phone_verification \
  --request-id unique-send-attempt-001

# Replace the ID with the saved send response. Sandbox only:
printf '123456' | node whatsos-otp-cli.mjs check \
  --id ver_REPLACE_WITH_SAVED_ID --code-stdin \
  --request-id unique-check-attempt-001

PowerShell · sandbox walkthrough
# WHATSOS_OTP_KEY must already be set in the process environment.
node .\whatsos-otp-cli.mjs send --to +12025550123 --purpose phone_verification --request-id unique-send-attempt-001
# Sandbox only. Replace the ID from the send response:
'123456' | node .\whatsos-otp-cli.mjs check --id ver_REPLACE_WITH_SAVED_ID --code-stdin --request-id unique-check-attempt-001

Replace the sample operation IDs with unique IDs for your attempts. The sample number is fictional. For live checks, pipe user input through secure stdin; avoid putting codes into shell history.

get, resend and cancel are supported. Run node whatsos-otp-cli.mjs --help for usage. Output is JSON. Exit codes: 0 successful operation or verified check, 2 unverified check, 1 error.

Prefer cURL? See the raw HTTP examples →

02 / APPLICATIONS

Connect your server.

These snippets show client calls inside your own backend handlers. attempt, submitted codes and business completion represent your application's session and persistence code; these snippets are not a complete authentication server.

Node.js

Node.js 18+ · server only
import { WhatsosOtp } from './whatsos-otp.mjs';
const otp = new WhatsosOtp({
  origin: 'https://whatsos.com', apiKey: process.env.WHATSOS_OTP_KEY
});
// attempt is loaded from YOUR server-side action/session store.
// Persist each operation key before calling the API.
const sent = await otp.send({
  to: attempt.phone, purpose: 'phone_verification',
  locale: 'en_US', reference: attempt.id
}, attempt.sendKey);
// Save sent.verification_id in that same attempt.

// In your separate check handler, load the bound attempt again:
const result = await otp.check(
  attempt.verificationId, userEnteredCode, attempt.checkKey
);
if (result.verified === true && result.status === 'verified') {
  // Atomically complete this bound action ONCE in your database.
}

Python

Python 3.10+ · standard library
import os
from whatsos_otp import WhatsosOtp, WhatsosOtpError
otp = WhatsosOtp(os.environ['WHATSOS_OTP_KEY'])
# attempt comes from YOUR server-side action/session store.
try:
    sent = otp.send(attempt['phone'], 'phone_verification',
                    request_id=attempt['send_key'], reference=attempt['id'])
    # Persist sent['verification_id'] in this attempt.
    # Later, in the check handler, load the bound attempt:
    result = otp.check(attempt['verification_id'], user_entered_code,
                       request_id=attempt['check_key'])
    if result.get('verified') is True and result.get('status') == 'verified':
        pass  # Complete the bound action once in your database.
except WhatsosOtpError as error:
    # Use error.status, error.code and error.retry_after to choose recovery.
    raise
# Transport failures: retain the exact request_id and body for retry.

PHP and other frameworks

PHP · server-side cURL
// PHP backend: cURL extension required.
function otp_post(string $path, array $body, string $requestId): array {
    $key = getenv('WHATSOS_OTP_KEY');
    if (!$key) throw new RuntimeException('OTP key is not configured');
    $ch = curl_init('https://whatsos.com/api/v1/otp' . $path);
    curl_setopt_array($ch, [
        CURLOPT_POST => true, CURLOPT_RETURNTRANSFER => true,
        CURLOPT_TIMEOUT => 15, CURLOPT_FOLLOWLOCATION => false,
        CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $key,
            'Content-Type: application/json', 'Idempotency-Key: ' . $requestId],
        CURLOPT_POSTFIELDS => json_encode($body, JSON_THROW_ON_ERROR)
    ]);
    $raw = curl_exec($ch);
    $status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
    curl_close($ch);
    if ($raw === false) throw new RuntimeException('Uncertain request; preserve operation key');
    $data = json_decode($raw, true, 512, JSON_THROW_ON_ERROR);
    if ($status < 200 || $status >= 300) {
        throw new RuntimeException('OTP request rejected; HTTP ' . $status);
    }
    return $data;
}
// $attempt must come from your server-side session, not a browser ID.
$result = otp_post('/verifications/' . rawurlencode($attempt['verification_id'])
    . '/check', ['code' => $userEnteredCode], $attempt['check_key']);
if (($result['verified'] ?? false) === true && ($result['status'] ?? '') === 'verified') {
    // Atomically complete the matching action once.
}

For Laravel, Django, Express, serverless functions and other frameworks, use the same API contract. Keep redirects disabled when sending credentials. Apply your application's session authentication or guest action binding, CSRF checks and rate limits. Handle HTTP errors and transport failures before approving any action.

Need delivery events? Verify signed webhooks →

03 / WORDPRESS

A plugin you can install.

WhatsOS OTP Verification includes an admin settings page and a responsive shortcode form with send, check, resend and cancel. The challenge stays bound to the visitor's server-side session.

Version 1.0.0 · WordPress 6.4+ · PHP 8.0+ with OpenSSL · HTTPS required for live use

  1. In WordPress, open Plugins → Add New → Upload Plugin. Upload the ZIP, install and activate.
  2. Open Settings → WhatsOS OTP. Enable forms and save a scoped test key with otp:send, otp:verify and otp:cancel.
  3. Match your project's purpose and language. Defaults are phone_verification and en_US.
  4. Add [whatsos_otp] to a Shortcode block or your page builder's shortcode widget.
  5. Test with code 123456. Complete live sender, template and licence setup before replacing the key with a live key.
Connect verification to your own workflow.

The plugin verifies phone ownership. It does not automatically create accounts, log users in or change WooCommerce checkout. A developer connects its server-side proof to the intended action.

Approve a matching action once

WordPress · protected server handler
// Inside YOUR protected WordPress server handler:
// Validate authorization, business input and the action's CSRF token first.
// Load the expected phone from the action you intend to approve.
$proof = whatsos_otp_consume($expected_phone, 'phone_verification');
if (is_wp_error($proof)) {
    return $proof; // Stop. The phone is not verified for this action.
}
// Complete the matching action once; record its unique completion ID.
// Test proofs are rejected by default.

A proof lasts five minutes after verification, belongs to this browser session and can be consumed once. The expected phone and purpose must match. Default consumption accepts live proofs only. Deduplicate your business action separately and handle failures between consumption and saving it.

The whatsos:verified browser event is only a UI signal. The optional PHP whatsos_otp_verified hook reports live verification; see the plugin readme for safe consumption and sandbox hooks.

Only one active challenge per browser session is supported. Allow the plugin's same-origin REST POST routes through caching/security layers. Requests go to WhatsOS when a visitor asks for or checks a code; update your site's privacy notice accordingly.

04 / CODING TOOLS

Give your coding tool the contract.

Use the OpenAPI file and implementation notes with your AI coding assistant or development CLI. The files describe the existing API, session binding, retries and test cases. They do not require a particular AI vendor.

Starter prompt · no credentials
Implement WhatsOS WhatsApp OTP phone verification in this project.
Read https://whatsos.com/otp/ai-integration.txt and
https://whatsos.com/otp/openapi.json first.
Use WHATSOS_OTP_KEY only on the backend and begin with a test project.
Bind phone, purpose, environment and verification ID to a server-side
action session. Add send, check, resend and cancel handling.
Reuse operation keys only for the same uncertain request; replace the
stored verification ID after resend. Require verified=true and
status=verified, then atomically complete the bound action once.
Add CSRF protection, request limits and tests for incorrect, expired,
replayed and cross-session codes. Do not send live messages while building.
For WordPress, use the plugin's server-side whatsos_otp_consume() function.

These are development resources, not a hosted MCP server or an automatic connector. Configure keys through your application's secret manager. Do not paste keys or real OTPs into prompts. A live send must follow the recipient's request for verification.

READY TO USE

Your integration toolkit.

Version 1.0.0 downloads
ResourceIncludes
Backend starter ZIP ↓Node client, CLI, Python client, OpenAPI and AI notes
WordPress plugin ZIP ↓Settings, shortcode, form assets and readme
Node.js client ↓Send, check, read, resend, cancel and webhook verification
Python client ↓Standard-library HTTP client
SHA-256 checksumsVerify downloaded ZIP files

Live API calls use your project's applicable licence and Meta billing. The toolkit does not change those rates. View current service pricing.

NEXT STEP

Start in your sandbox.

Create a test project and your first scoped API key.

Open OTP workspace ↗

Invoices & receipts API

Send transactional WhatsApp messages from POS, websites, Shopify and billing software using your developer project.

Read the transactional messaging guide