Send WhatsApp alerts from your own code

$29 a month · no number of your own · no Meta verification

Jabee sends WhatsApp alerts over Meta's official Cloud API with no phone number of your own and no Meta verification, because the number and the template are ours. One POST, and it lands on a phone in about a second.

curl https://api.jabee.ai/api/v1/alerts \
  -H "Authorization: Bearer $JABEE_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Nightly build failed",
    "body":  "main @ 4f2a9c. Three tests red in billing.",
    "url":   "https://ci.example/runs/8821"
  }'

Try it now for free

Why this is not the usual answer

Search for sending WhatsApp from your own code and almost everything you find asks you to scan a QR code and drives your personal WhatsApp account. It works until it does not. Running an unofficial client against WhatsApp is what gets numbers banned, and the number it gets banned is yours.

The official route does not ban anybody, and asks for a verified Meta business, a registered phone number and an approved message template before you can send a single line. That is days of work for a build notification.

Jabee is both. It runs on the official Cloud API, as a Meta Tech Provider on a verified business portfolio, and you need none of that, because the number and the template are ours and were approved long ago. There is no number of yours to get banned.

What you do not need

Four things stand between a developer and one official WhatsApp message. You need none of them, because they are ours and were done long ago.

One thing to be exact about, because plenty of pages are not: Meta does now let a business start on the Cloud API with verification still pending, under limits it hard-codes and does not let you lift. So "you cannot send without verification" is not the claim. The claim is narrower and still true nowhere else: you need no number, no portfolio, no app and no template of your own, at any stage, ever.

The long version of this question — what Meta actually requires, what you can send without it, and the four things this cannot do — is on its own page: the WhatsApp API without your own number or business verification.

It is not a sandbox, and not five test numbers

Meta hands every new Cloud API developer a test number, and it is a real thing that sends real messages — to five recipients, each of which has to be added to an allowlist and verified by a code Meta sends them. It is enough to see JSON come back. It is not enough to tell your on-call engineer that the queue is backing up.

This is not that. The number is a registered, Meta-verified production number, and a message to a colleague who verified their phone once is an ordinary production send. There is no allowlist to maintain and no sandbox to graduate from, because there is no sandbox. The first three sends are free so you can see one arrive; after that it is the same endpoint doing the same thing.

What you get for the call

From your language, with no SDK

It is an HTTP endpoint with a bearer token and a JSON body, so there is nothing to install in any language. The curl above is the whole contract; here it is in Node and in Python.

// Node 18+, no dependencies
await fetch("https://api.jabee.ai/api/v1/alerts", {
  method:  "POST",
  headers: {
    Authorization:  `Bearer ${process.env.JABEE_KEY}`,
    "Content-Type": "application/json"
  },
  body: JSON.stringify({
    title: "Nightly build failed",
    body:  "main @ 4f2a9c. Three tests red in billing.",
    url:   "https://ci.example/runs/8821"
  })
});
# Python, requests
requests.post(
    "https://api.jabee.ai/api/v1/alerts",
    headers={"Authorization": f"Bearer {os.environ['JABEE_KEY']}"},
    json={
        "title": "Nightly build failed",
        "body":  "main @ 4f2a9c. Three tests red in billing.",
        "url":   "https://ci.example/runs/8821",
    },
    timeout=10,
)

PHP, Go, Ruby, Java, C#, a shell script in a cron entry — if it can make an HTTPS request it can send an alert. The reference lists every field.

And from the things you already run

There is no plugin to install, because the endpoint takes a plain JSON body: a title, an optional body, an optional url. What that means in practice depends on whether the thing sending the alert lets you decide what it posts.

Where you write the body yourself, it is one call. A curl in a cron entry or a systemd timer — the job that silently stopped running three weeks ago is the classic case. A failure step in GitHub Actions or your deploy script, with the run URL in the url field so the message is one tap from the logs. An HTTP request node in n8n, Zapier, Make or Power Automate. Or your own application: a payment that bounced, a refund over a threshold, a sign-up from a domain you have been chasing.

Worth knowing about the automation tools: they can already send WhatsApp themselves, if you bring your own number, your own business account and your own approved template. This is the version where you bring none of that.

Monitoring tools post a shape of their own, so for the commonest one we read theirs. A Grafana webhook contact point goes straight at /api/v1/alerts/grafana with your key on the Authorization header and nothing in between — no notification template, no Grafana 12, Grafana Cloud included. Prometheus Alertmanager posts to the same URL, because Grafana's body is Alertmanager's shape extended. The two-minute setup is here.

Everything else has a page with the actual configuration on it, rather than a paragraph of encouragement:

What you runWhat it takes
Grafana, AlertmanagerA webhook contact point and a key. Nothing in between.
Uptime KumaThe Webhook notification type, with a custom body.
ZabbixA webhook media type — twenty lines of script, which is how Zabbix does every integration.
GitHub ActionsOne step with if: failure() and the run URL in it.
cron, systemdA || after the job, or one OnFailure= unit for the whole machine.
n8n, Make, ZapierAn HTTP request node with the key on a header.
Home AssistantA rest_command and one automation.
Claude CodeA Stop hook, or the MCP server so the agent asks you itself.

A tool that posts a fixed shape of its own and is not on that list needs a few lines in the middle to translate, until we read its shape too — Grafana's is the one we read so far.

Where it goes: one handset per business

There is nothing to address. An alert goes to the one phone your business verified, or to the account owner's phone if you have not verified another — which is what lets this work the moment you have an API key, with nothing to set up first.

Verifying a different phone takes one message: open Settings, tap the link, and send the code from the handset that should get the alerts. An ops phone, a shared on-call handset, a tablet on the wall.

-d '{
    "title": "Payment bounced on #8821",
    "body":  "Order #8821, AED 450, card declined"
  }'

There is no rota and no second recipient, and recipient or team in the body is refused with a 400 rather than quietly ignored — an alert that reports success to a phone nobody is watching is worse than an error. To reach several people, connect your own WhatsApp number and send from there: alerts on our number spend our standing with Meta, and that cost belongs with whoever generates the volume.

One rule worth knowing before you build on it

Alerts go to your own verified people, not to your customers. Messaging strangers from a shared number is what gets that number banned, so we do not do it, and nothing is delivered to a phone whose owner has not confirmed it.

The same rule has a second half. If somebody never replies to anything — three in a row — we stop sending to that handset and tell you, and anything they type to us clears it. Every other provider's notifications are fire-and-forget; ours are not, and the reason is the reason the number still works.

To reach your customers you connect your own number, and then it is your number and your relationship. That is the inbox and the assistant, not this.

Approvals: the same call with a question on it

Sometimes you do not want to tell somebody, you want to ask. Post to /api/v1/approvals instead and the message arrives with buttons: approve, skip, or edit, which comes back as free text. The answer reaches you on the same signed webhook.

curl https://api.jabee.ai/api/v1/approvals \
  -H "Authorization: Bearer $JABEE_KEY" \
  -d '{
    "title":   "Refund AED 450 to Sara",
    "options": ["approve", "skip", "edit"]
  }'

It is the same product and the same $29. One tells, one asks.

Human in the loop, for an agent that is about to do something

This is the shape most people arrive looking for. An AI agent is about to refund a customer, email a client, delete a branch or push to production, and it should ask first. The usual answer puts that question in a web inbox or a company chat tool, which means the approver has somewhere else to be looking. Here the question is a WhatsApp message, which they already have open, and the answer is a button.

There is an MCP server, so no code is needed at all: npx @jabee/mcp and one environment variable give an agent in Claude Code, Cursor or any MCP client three tools — ask_person, check_approval and tell_person. The blocking wait is built in, with a default of two minutes and then a request id to poll, because an agent held open on a tool call is an agent whose client eventually gives up.

The same key covers the other half of a long agent run: a WhatsApp message when it finishes, so you can leave the terminal and know when to come back. Setting up the MCP server takes about a minute.

What it costs

$29 a month, for 500 alerts and approvals together, then 3 cents each. No setup fee and no contract.

The first three are free, so you can point a key at your own phone and watch one arrive before you pay for anything.

Comparable tools in November 2026 run from about $10 a month to about $99, and the best-known name in this category, HumanLayer, no longer sells an approvals API at all.

Questions

Can I send WhatsApp alerts without my own number?

Yes. They go out on Jabee's number, which is already registered with Meta and already has an approved template. You never register a number, never verify a business and never submit a template.

Do I need Meta business verification?

No. That is the part this skips. Sending on the official Cloud API normally requires a verified Meta business portfolio, a registered phone number and an approved message template. We have all three; you need an API key.

Will my number get banned?

There is no number of yours involved, so there is nothing of yours to ban. The tools that get numbers banned drive your personal WhatsApp account through an unofficial client. Jabee runs on Meta's official Cloud API as a Tech Provider.

Can I send to my customers?

No, and that is deliberate. Alerts go to your own verified people. Messaging strangers from a shared number is what gets that number banned. To reach your customers you connect your own number, which is the inbox.

What happens if nobody answers?

The request expires at the time you set and your webhook is told. Nothing hangs. If the person has no WhatsApp linked, or their phone refused the message, it falls back to email with the same three buttons on a page.

Can two people answer at once?

Only one wins. The response is recorded in a single statement, so a second tap gets told what already happened rather than overwriting it.

How do I know the callback is really from you?

Every webhook carries an HMAC signature over the raw body, using a secret you set. Compare it in constant time and reject anything that does not match. If you would rather not run an endpoint at all, poll the request by id instead.

Is there an MCP server?

Yes. Run it with npx @jabee/mcp and one environment variable, and your agent gets three tools: ask_person, check_approval and tell_person. It needs no WhatsApp number of your own. How to set it up.

What does it cost?

$29 a month, flat, with no per-request charge. Notifications are in the same plan, because a notification is an approval without a question.

Can I use the WhatsApp API without a Meta business account?

For alerts and approvals, yes. You create no Meta business account, no developer app and no WhatsApp Business Account, because the sending happens on ours, which is already verified and already has an approved template.

One thing to be exact about: Meta does now let a business start on the Cloud API with its own verification still pending, under limits it hard-codes. So the claim is not that sending without verification is impossible — it is that you need no number, no portfolio, no app and no template of your own, at any stage.

Is this a WhatsApp Cloud API sandbox or test number?

No. Meta's own test number sends real messages to five recipients, each added to an allowlist and verified by a code Meta sends them — enough to see JSON come back, not enough to page an on-call engineer.

Jabee sends from a registered, Meta-verified production number, so a message to a colleague who verified their phone once is an ordinary production send with no allowlist to maintain. The first three are free so you can watch one arrive.

Can I send from Python, Node or a shell script?

From anything that can make an HTTPS request. It is a POST with a bearer token and a JSON body, so there is no SDK to install in any language. Node and Python are above; PHP, Go, Ruby, Java, C# or a cron entry work the same way.

Can Grafana, Zabbix, cron or GitHub Actions send through this?

Yes. The endpoint takes a title, a body and a url, so anywhere you write the request yourself it is a single call: curl in a cron entry, a failure step in GitHub Actions, an HTTP request node in n8n, Zapier, Make or Power Automate.

Grafana has a route of its own that reads Grafana's body, so a webhook contact point points at /api/v1/alerts/grafana with no template and nothing in between, on any Grafana version including Cloud. Prometheus Alertmanager uses the same URL. The setup takes two minutes.

There is a page with the real configuration for each of Grafana, Uptime Kuma, Zabbix, GitHub Actions, cron and systemd, n8n, Make and Zapier and Home Assistant.

Can I get a WhatsApp message when Claude Code finishes?

Yes, two ways. A Stop hook can curl the alerts endpoint when a turn ends, which needs no MCP server and is one line of JSON. Or run npx @jabee/mcp and the agent gets tell_person, which sends the message itself and can say what it did. Both, with the config.

Get an API key