Send WhatsApp OTP in Go

Need to verify a WhatsApp number from your Go app? It's two REST calls — POST /v1/send to send the OTP, POST /v1/verify to check the code. The snippet below uses only net/http from the standard library, so you can paste it and go.

Go 1.21+ · standard library only, no dependencies

10 free OTPs on signup — no credit card required.

1. Send an OTP

Generate an API key, then POST the destination number to /v1/send. OTP Space returns 202 Accepted once the message is queued for WhatsApp delivery.

otp.go
package otp

import (
	"bytes"
	"encoding/json"
	"fmt"
	"net/http"
)

// apiKey comes from https://app.otpspace.com/dashboard/api-keys.
// Keep it server-side — never ship it in a mobile or browser client.
const apiKey = "sk_live_xxx"

const baseURL = "https://api.otpspace.com/v1"

// SendOTP sends a WhatsApp OTP to an Indonesian number (E.164, e.g.
// "+6281234567890"). OTP Space replies 202 Accepted once it is queued.
func SendOTP(phone string) error {
	payload, _ := json.Marshal(map[string]string{"phone": phone})

	req, _ := http.NewRequest(http.MethodPost, baseURL+"/send", bytes.NewReader(payload))
	req.Header.Set("Authorization", "Bearer "+apiKey)
	req.Header.Set("Content-Type", "application/json")

	res, err := http.DefaultClient.Do(req)
	if err != nil {
		return err
	}
	defer res.Body.Close()

	if res.StatusCode != http.StatusAccepted { // 202
		return fmt.Errorf("otp send failed: %s", res.Status)
	}
	return nil
}

2. Verify the code

POST the same number plus the code the user entered to /v1/verify. A 200 OK means the code is correct; every number gets up to 5 attempts before the OTP locks.

verify.go
// VerifyOTP checks the code the user typed against the OTP that was sent to
// their number. A 200 OK means the code is correct; anything else (422 wrong
// code, 410 expired, 429 too many attempts) means it is not.
func VerifyOTP(phone, code string) (bool, error) {
	payload, _ := json.Marshal(map[string]string{"phone": phone, "code": code})

	req, _ := http.NewRequest(http.MethodPost, baseURL+"/verify", bytes.NewReader(payload))
	req.Header.Set("Authorization", "Bearer "+apiKey)
	req.Header.Set("Content-Type", "application/json")

	res, err := http.DefaultClient.Do(req)
	if err != nil {
		return false, err
	}
	defer res.Body.Close()

	return res.StatusCode == http.StatusOK, nil // 200 = verified
}

What the API returns

A successful send responds immediately with the masked destination, an otp_id you can track, and your remaining credits.

202 Accepted
{
  "success": true,
  "data": {
    "otp_id": "otp_abc123def456",
    "destination": "6281234***90",
    "channel": "whatsapp",
    "status": "queued",
    "expires_at": "2026-07-17T10:05:00Z"
  },
  "credits_remaining": 994
}

Built for Indonesian apps

OTP Space delivers one-time passwords over WhatsApp to every Indonesian carrier through two REST calls — no WhatsApp Business API setup, no template approvals, no SDK to install. It works the same from any language: sign up, generate a key, and send. The examples here use only the standard library so you can drop them straight into an existing service.

Other languages

Node.js PHP

Send your first WhatsApp OTP today

Sign up free, generate your API key, and integrate in two REST calls — no credit card, no sales call, no WhatsApp Business verification.