Developer documentation

Integrate WhatsApp OTP in minutes.

Your server sends requests to the WhatsAppOTP API. Keep the project API key on your server and never expose it in browser JavaScript.

Authentication

Server-side API key

Add the project key to every developer API request:

Authorization: Bearer wa_live_xxxxx

API keys are permission-scoped. For a login-only integration, grant only otp:send and otp:verify. Add message, consent, or campaign scopes only when that integration actually uses them.

Least privilege

Available API key scopes

otp:send Send OTP otp:verify Verify OTP messages:send Send transactional messages messages:read Read delivery state consents:read Read consent consents:write Manage consent campaigns:read Read campaigns campaigns:write Create campaigns
OTP

Send and verify codes

curl -X POST https://api.stuff4pc.com/v1/otp/send \ -H "Authorization: Bearer wa_live_xxxxx" \ -H "Idempotency-Key: order-login-12345" \ -H "Content-Type: application/json" \ -d '{"to":"+639171234567"}'

POST the returned verificationId and the six-digit code to /v1/otp/verify. Codes expire automatically and are stored only as hashes.

JavaScript / TypeScript

Server SDK

import { WhatsAppOtpClient } from "@whatsappotp/sdk"; const client = new WhatsAppOtpClient({ baseUrl: "https://api.stuff4pc.com", apiKey: process.env.WHATSAPPOTP_API_KEY!, }); const sent = await client.sendOtp( { to: "+639171234567" }, { idempotencyKey: crypto.randomUUID() } );
Transactional

Send normal WhatsApp messages

POST /v1/messages { "to": "+639171234567", "text": "Your order #1234 is ready." }

Use GET /v1/messages/:messageId or webhooks for asynchronous delivery status. Direct-message state progresses through QUEUED, SENDING, SENT, DELIVERED and READ when WhatsApp receipts are available; terminal failures use FAILED.

Images, videos and documents

POST /v1/messages/media { "to": "+639171234567", "type": "IMAGE", "url": "https://cdn.example.com/order-ready.jpg", "caption": "Your order is ready." }

Media must use a public HTTPS URL. The worker rejects redirects, private/reserved destinations, invalid MIME types, empty files, images larger than 16 MB, and video/document files larger than 32 MB. Documents require a filename.

Marketing

Consent before campaigns

Record OPTED_IN consent using /v1/consents before creating a campaign. The API rejects recipients without active consent or recipients on the suppression list. Inbound opt-out keywords are processed automatically. Campaigns may also include one optional IMAGE, VIDEO, or DOCUMENT using the same secure public-HTTPS media pipeline as transactional media messages. A queued campaign can be stopped with POST /v1/campaigns/:id/cancel; recipients that have not started delivery are marked BLOCKED and stale queue jobs are ignored by the worker.

Webhooks

Signed asynchronous events

Create webhook endpoints in the dashboard. Verify the x-whatsappotp-signature header by computing HMAC-SHA256 over timestamp + "." + the exact raw request body. The message.received event is emitted only for new one-to-one inbound messages; media events include metadata/caption only and the platform does not automatically download inbound media.

otp.verified message.received message.sent message.delivered message.read message.failed connection.connected connection.disconnected connection.logged_out consent.opted_out

The included JavaScript, PHP, and Python SDKs now provide a webhook signature verifier with a default five-minute timestamp tolerance to reject replayed requests.

Reliability

Retries, idempotency and request IDs

Send Idempotency-Key on OTP sends, transactional sends, and campaign creation. Reusing a key with the same body returns the original result; changing the body returns HTTP 409.

Every API response includes x-request-id. Store it with your application logs when troubleshooting.

PHP

Dependency-free PHP client

A PHP 8.1+ cURL client is included under integrations/php. It supports OTP, verification, transactional messages, consent, campaigns, idempotency keys, client-IP forwarding and request-ID errors.

Python

Dependency-free Python client

A Python 3.11+ standard-library client is included under integrations/python with the same server-side API coverage and retry controls.

WordPress / WooCommerce

Included WordPress plugin

The repository contains integrations/wordpress/whatsappotp. Configure the API URL and project key in WordPress settings, then use the shortcode [whatsappotp_verify].

Shopify

Keep the secret in an app backend

Never place the project secret in Liquid or storefront code. Your Shopify app backend calls WhatsAppOTP and the storefront talks only to your app backend. A server-side integration guide is included under integrations/shopify.