Recipe · Makers

Your sensors, on WhatsApp.

Greenhouse too cold, water tank full, garage door opened at 3am — the board POSTs, your phone buzzes. One HTTPS request to POST /v1/notify from whatever the thing runs: Arduino C++ on an ESP32, MicroPython, or a cron line on a Raspberry Pi. No app to install on the phone, no linked device, no phone-number pairing — it's the official Meta Cloud API underneath.

§ 1

ESP32 / Arduino (C++)

WiFiClientSecure + HTTPClient, both in the ESP32 Arduino core — no extra libraries. Call notify() from wherever your sketch decides something's worth a buzz. Get the key by sending join on WhatsApp (details at the bottom).

greenhouse.ino — sketch excerpt
#include <WiFi.h>
#include <WiFiClientSecure.h>
#include <HTTPClient.h>

#define PINGWA_KEY "pw_your_key_here"

// call after WiFi.begin(...) has connected
void notify(const String &text) {
  WiFiClientSecure client;
  // Trade-off, stated plainly: setInsecure() still encrypts the
  // connection but skips certificate validation — fine for a
  // greenhouse ping, wrong for anything secret. The proper fix is
  // client.setCACert(root_ca) with the root CA PEM in your sketch.
  client.setInsecure();

  HTTPClient http;
  http.begin(client, "https://pingwa.dev/v1/notify");
  http.addHeader("Authorization", "Bearer " PINGWA_KEY);
  http.addHeader("Content-Type", "application/json");
  int code = http.POST("{\"text\": \"🌡️ greenhouse 4°C\"}");
  http.end();  // code == 200 → queued; negative → connection/TLS error
}
§ 2

MicroPython

urequests ships with standard MicroPython builds for the ESP32 — import urequests just works, no mip install needed. The json= argument handles the body and the Content-Type header for you.

main.py — MicroPython on ESP32
import urequests

def notify(text):
    r = urequests.post(
        "https://pingwa.dev/v1/notify",
        json={"text": text},
        headers={"Authorization": "Bearer pw_your_key_here"},
    )
    r.close()

notify("💧 tank full — pump stopped")
§ 3

Raspberry Pi — or anything with a shell

If it runs cron and curl, it can tap you. The || true matters: a ping that fails (WiFi blip, our outage) must never break the job it's reporting on.

crontab — nightly done-ping
0 22 * * * /home/pi/backup.sh && curl -sf -X POST https://pingwa.dev/v1/notify -H "Authorization: Bearer $PINGWA_KEY" -H "Content-Type: application/json" -d '{"text": "🍓 pi backup done"}' || true

For threshold sensors, the trap is alert-per-reading: the tank crosses 90% and every 5-minute poll fires another message. The Idempotency-Key header fixes it server-side — the same key with the same body is honored for 24 hours, so replays are absorbed and nothing is re-sent. Key it on the state plus the day and you get one alert per state-change per day, straight from a dumb polling loop:

tank-alert.sh — polled every 5 min, alerts once a day
#!/bin/sh
level=$(cat /var/lib/tank/level)   # your sensor read here
if [ "$level" -gt 90 ]; then
  curl -sf -X POST https://pingwa.dev/v1/notify \
    -H "Authorization: Bearer $PINGWA_KEY" \
    -H "Content-Type: application/json" \
    -H "Idempotency-Key: tank-high-$(date +%F)" \
    -d '{"text": "💧 tank above 90% — check the pump"}' || true
fi

One rule to respect: keep the body constant for a given key. A different body under the same key is rejected with a 409 and nothing is sent — so don't interpolate the live reading into the alert text, or the second poll's "91%" vs the first's "90.4%" turns your dedupe into a silent drop.

§ 4

Coming from CallMeBot?

Respect where it's due

CallMeBot has carried the maker crowd's WhatsApp pings for years — free for personal use, proven in a thousand forum threads, and run as a labor-of-love hobby project. If all you need is a one-way ping to yourself with zero budget, CallMeBot works — this page isn't here to tell you otherwise.

What's different here

  • Official Meta Cloud API — no linking your personal number to a third-party gateway; messages come from a registered business number.
  • Two-wayPOST /v1/ask sends a question with buttons and blocks until you tap; the board can ask, not just tell (see FAQ).
  • Hosted service with an SLA — a status page, uptime commitments, and someone on the hook when it breaks.
  • Agent-native docsllms.txt means your coding agent can wire this in without you reading anything.

Pick by what you're protecting: a hobby ping, either. Something you'd be annoyed to miss — that's what the paid path is for.

§ 5

FAQ

ESP32 send WhatsApp message without CallMeBot?

That's § 1 — a plain HTTPS POST to /v1/notify with a Bearer key, over the official Meta Cloud API. No phone-number pairing, no linked device, no waiting for an activation message: send join once, put the key in your sketch, POST.

How many messages does the free tier cover?

30 paid messages a month, and your replies inside the 24h window are free. That's plenty for events — and the discipline is the point: sensor chatter belongs behind thresholds and the Idempotency-Key pattern from § 3, not raw readings. If your board sends more than 30 paid messages a month, it's not alerting you, it's logging at you.

Does an ESP8266 work too?

Same HTTP, same endpoint — the 8266's Arduino core has WiFiClientSecure and HTTPClient as well. Two caveats from the smaller chip: heap is tight, so keep the JSON body short; and TLS on the 8266 usually forces setInsecure() (or a fingerprint pin) in practice — the § 1 trade-off comment applies double.

Can the board ask me something?

Yes — POST /v1/ask sends the text with up to three buttons and long-polls for your tap; the response tells your code which button (b0/b1/b2) you pressed. "Frost expected — run the heater?" is one request. Most sensor work only needs notify, so we'll leave it at that here — the full contract is in llms.txt.

QR code to join pingwa on WhatsApp

Scan the code and get instant access. It opens WhatsApp with “join” ready to send, and your API key comes straight back.

The snippets above are the honest shape of the integration, not lab-verified on every board revision — pin versions and test on your own hardware before trusting a greenhouse to it.