WAservix Go integration
Connect WAservix to your Go app: send WhatsApp messages from your own WhatsApp number, check delivery and receive replies by webhook. Copy the examples, add your key and run.
Requirements
Go 1.22+ (standard library only).
Add your API key
Create a key under WAservix → Devices → API key (it starts with wpk_). Keep it on your server, in an environment variable or secret store. Never put it in a website, a mobile app or a public repository.
export WASERVIX_KEY=wpk_your_key
export WASERVIX_WEBHOOK_SECRET=your_webhook_secret
Set up the client
Base URL https://tekservix.com/waservix/api. Send the key as Authorization: Bearer wpk_….
// The calls below go inside func main() or your own function.
import (
"fmt"
"io"
"log"
"net/http"
"os"
"strings"
"time"
)
Send a WhatsApp message
Messages are queued and sent one at a time per number, so the answer comes back at once with "status": "in_progress" and a msgId.
req, err := http.NewRequest("POST", "https://tekservix.com/waservix/api/send-message", strings.NewReader(`{"to": "+250788123456", "text": "Hello Aline, your order is ready"}`))
if err != nil {
log.Fatal(err)
}
req.Header.Set("Authorization", "Bearer "+os.Getenv("WASERVIX_KEY"))
req.Header.Set("Content-Type", "application/json")
client := &http.Client{Timeout: 30 * time.Second}
res, err := client.Do(req)
if err != nil {
log.Fatal(err)
}
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
if res.StatusCode >= 400 {
log.Fatalf("API error %d: %s", res.StatusCode, body)
}
fmt.Println(string(body))
Send a document or image
Use imageUrl, videoUrl, audioUrl or documentUrl with a public https link. Groups work too: put the group JID (…@g.us) in to.
req, err := http.NewRequest("POST", "https://tekservix.com/waservix/api/send-message", strings.NewReader(`{"to": "+250788123456", "text": "Your invoice", "documentUrl": "https://example.com/inv-1042.pdf", "fileName": "Invoice-1042.pdf"}`))
if err != nil {
log.Fatal(err)
}
req.Header.Set("Authorization", "Bearer "+os.Getenv("WASERVIX_KEY"))
req.Header.Set("Content-Type", "application/json")
client := &http.Client{Timeout: 30 * time.Second}
res, err := client.Do(req)
if err != nil {
log.Fatal(err)
}
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
if res.StatusCode >= 400 {
log.Fatalf("API error %d: %s", res.StatusCode, body)
}
fmt.Println(string(body))
Check message status
status is queued, sent, delivered, read, played or failed. Webhooks tell you without polling.
req, err := http.NewRequest("GET", "https://tekservix.com/waservix/api/messages/58213/info", nil)
if err != nil {
log.Fatal(err)
}
req.Header.Set("Authorization", "Bearer "+os.Getenv("WASERVIX_KEY"))
client := &http.Client{Timeout: 30 * time.Second}
res, err := client.Do(req)
if err != nil {
log.Fatal(err)
}
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
if res.StatusCode >= 400 {
log.Fatalf("API error %d: %s", res.StatusCode, body)
}
fmt.Println(string(body))
Receive WhatsApp messages by webhook
Set a webhook URL and events for the number under WAservix → Devices. Each request carries X-Webhook-Signature, which equals that device’s webhook secret. Compare it in constant time, answer 2xx quickly and process the message after answering (we retry 3 times).
// extra imports: "crypto/hmac", "crypto/sha256", "crypto/subtle", "encoding/hex", "encoding/json" (use the ones you need)
func waservixWebhook(w http.ResponseWriter, r *http.Request) {
raw, err := io.ReadAll(io.LimitReader(r.Body, 1<<20))
if err != nil {
http.Error(w, "bad body", http.StatusBadRequest)
return
}
if subtle.ConstantTimeCompare([]byte(os.Getenv("WASERVIX_WEBHOOK_SECRET")), []byte(r.Header.Get("X-Webhook-Signature"))) != 1 {
http.Error(w, "bad signature", http.StatusUnauthorized)
return
}
var event struct {
Event string `json:"event"`
Data struct {
Messages struct {
Key struct {
CleanedSenderPn string `json:"cleanedSenderPn"`
} `json:"key"`
MessageBody string `json:"messageBody"`
} `json:"messages"`
} `json:"data"`
}
if err := json.Unmarshal(raw, &event); err != nil {
http.Error(w, "bad json", http.StatusBadRequest)
return
}
w.WriteHeader(http.StatusOK)
if event.Event == "messages.received" {
log.Printf("WhatsApp from %s: %s", event.Data.Messages.Key.CleanedSenderPn, event.Data.Messages.MessageBody)
}
}
// http.HandleFunc("POST /webhooks/wapenda", waservixWebhook) // Go 1.22+
Errors, limits and retries
Every answer has success; errors add a readable message. 401 means a wrong key, 402 no active plan for this number or phone, 409 the number or phone isn’t connected, 429 too many requests (300 a minute per key): wait for the Retry-After seconds and try again. Retry 5xx and network errors with a back-off, but don’t blindly retry a send that may have worked: check its status first, or you could send twice.
Full list of endpoints and fields: WAservix API reference.
Questions
Is this the official WhatsApp Business API?
No. WAservix links your own number as a companion device, like WhatsApp Web, so there is no Meta approval. Only message people who expect to hear from you: WhatsApp can ban numbers that spam.
Can I call the API from a mobile app or browser?
Don’t. Anyone could read the key from the app or page. Call the API from your server and let your app talk to your server.