Skip to content
Start free

Authentication

Wabery uses API keys to authenticate requests and a signing secret to verify the webhooks Wabery sends you.

The fastest way to get a project-scoped key is the CLI:

Terminal window
npm i -g @wabery/cli
wabery login # opens the browser, choose a project, paste the shown key once

wabery login creates an API key for the project you select and stores it in your local CLI config, so the CLI and the MCP server are authenticated automatically after that first paste. Use wabery doctor to confirm it works. Create projects in the dashboard, then open Access → API keys to create, reveal, scope, or revoke a project key.

Keys are prefixed by environment:

Prefix Use
wab_live_ Production traffic on your connected channels.
wab_test_ The shared sandbox number, for development.
wab_pub_ Browser-safe publishable key for registration intents.

For your own services, set WABERY_API_KEY (it overrides the CLI config) and authenticate every request with a Bearer token:

Terminal window
curl https://api.wabery.com/v1/messages \
-H "Authorization: Bearer $WABERY_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "channel_id": "channel_...", "conversation_id": "conversation_...", "text": "Hi" }'

The SDK reads the key for you:

import { Wabery } from "@wabery/sdk";
const wabery = new Wabery();

Publishable keys (wab_pub_...) are safe to use in browser widgets, but only on the registration-intent endpoints. Send them in the x-wabery-publishable-key header, not as a Bearer token:

Terminal window
curl https://api.wabery.com/v1/registration-intents \
-H "x-wabery-publishable-key: $WABERY_PUBLISHABLE_KEY" \
-H "Content-Type: application/json" \
-d '{ "customer_reference": "user_123" }'

The SDK and CLI do this automatically when apiKey / WABERY_API_KEY starts with wab_pub_.

Each webhook endpoint has a signing secret. Wabery signs every delivery so you can confirm it really came from Wabery and wasn’t tampered with — the signature arrives in the x-wabery-signature header as sha256=<hex>. See Webhooks for verification.

API keys carry a set of scopes that limit blast radius. A request missing the required scope returns 403 with error: "insufficient_scope" and the required_scope in the body. Grant the narrowest set each integration needs:

Scope Grants
messages:send Send messages.
conversations:read List conversations and read message history.
contacts:read / contacts:write Read / enroll and update contacts.
contacts:erase Erase a contact’s retained personal data.
broadcasts:read / broadcasts:write / broadcasts:send Read / create and manage / deliver broadcast campaigns.
templates:read / templates:write Read / create WhatsApp templates.
channels:read / channels:write List and inspect / update channel routing.
business_agents:read / business_agents:write Inspect / provision and manage Meta Business Agents, connectors, tools, settings, thread control, and skills.
flows:read / flows:send / flows:publish Read / send / publish WhatsApp Flows.
functions:read / functions:write / functions:invoke Read, deploy/manage, and invoke hosted functions.
submissions:read / dispatches:read Read Flow submissions / dispatches.
projects:read / projects:write Read / update project settings (webhook URL, routing).
config:read / config:write Read / apply config-as-code.
registrations:create Mint registration intents (also granted to wab_pub_ keys).
limits:read Read the key’s rate limits and quota.

A wildcard (*) key grants every scope — use it only for trusted server-side automation.