Need to send verification codes (OTP) from my application?
Almost every application needs phone verification, and almost every developer rewrites the flow — usually with the same holes: the code stored in plain text, no expiry, no attempt limit, and reusable forever.
WACO provides that flow complete. Your application only has to draw the screen.
Enabling it (once)
Open Developer in the dashboard → the Ready-made OTP card → press Enable OTP. We create the official verification template on your own WhatsApp number. Templates of this kind are usually approved by Meta instantly, and Meta writes the wording — you do not have to think about the sentence.
1. Send a code
POST /api/v1/otp/kirim
Authorization: Bearer waco_YOUR_KEY
Content-Type: application/json
{ "nomor": "628123456789", "ref": "order-123" }
Response:
{ "ok": true, "kedaluwarsa_pada": "2026-08-14T10:05:00.000Z" }
ref is yours to fill — a transaction id, a user id, anything. It comes back on
verification, so you do not need to keep the mapping yourself.
2. Verify the code
POST /api/v1/otp/periksa
Authorization: Bearer waco_YOUR_KEY
Content-Type: application/json
{ "nomor": "628123456789", "kode": "123456" }
{ "ok": true, "valid": true, "ref": "order-123" }
valid field, not the status code.
On failure there is a machine-readable alasan (reason):
| alasan | Meaning |
|---|---|
salah | Code does not match. sisa_percobaan tells you the attempts left. |
kedaluwarsa | Older than 5 minutes. Request a new code. |
terlalu_banyak_percobaan | Five wrong attempts. A new code must be sent. |
sudah_dipakai | Correct code, but it was already used. |
tidak_ada | No code was ever sent to that number. |
The rules we already enforce
- A 6-digit random code, generated with a cryptographic random source.
- Stored as a SHA-256 hash, never in the clear — a database leak does not let anyone complete somebody else's verification.
- Valid for 5 minutes.
- At most 5 attempts, then a new code is required.
- Single use — a correct code expires immediately.
- One active code per number; a new code voids the previous one.
- Re-requests for the same number are refused for 60 seconds. That also protects your bill from an application that accidentally loops.
Cost
Every code is one authentication-category message — billed by Meta directly to your account at their rate, with no markup from us. Rates differ by the recipient's country; look yours up on Meta's rate card.
The machine spec is in OpenAPI. Message not arriving? See the diagnosis guide.