Quickstart
Create an API key, check it with your first call, send a WhatsApp message, and receive replies at your own endpoint.
About ten minutes from nothing to a working integration. You need a Gauge workspace on the Growth or Scale plan, and a member role that can create API keys.
Create an API key
In the console, open Developers → API keys and choose Create key.
- Name it after the integration that will use it ("CRM sync"), so the request log reads well.
- Pick scopes. Grant only what this integration needs. For this quickstart:
connections:readandmessages:write. You can only grant scopes your own role can use; the rest are shown but disabled, with the reason. - Choose live or test. A test key reaches sandbox data only. See Environments.
- Optionally pin the key to one App, restrict it to your servers' IP addresses, or give it an expiry.
Copy the key when it is shown. It is shown once. Gauge stores only a hash, so a lost key cannot be recovered, only replaced.
A key looks like pulse_k_live_ followed by 32 characters (pulse_k_test_… for a test key). Store
it as a secret on your server, never in a browser or a mobile app.
export GAUGE_API_KEY="pulse_k_live_..."A key acts as you
An API key is tied to the member who created it. It can do what that member can do in the console, within the scopes you picked, and nothing more. If that member leaves the workspace, the key stops working. See Keys belong to a person.
Make your first call
GET /v2/me answers for any valid key. It tells you who the key is, what it may do, and how much
rate-limit budget is left: the quickest way to check a setup.
curl https://app.gauge.chat/backend/v2/me \
-H "Authorization: Bearer $GAUGE_API_KEY"{
"key": {
"id": "6f1c2a7e-0b8d-4c39-9a51-2f7d3e8b1c40",
"name": "CRM sync",
"prefix": "pulse_k_live_x9Qa",
"environment": "live",
"scopes": ["connections:read", "messages:write"],
"pinnedAppId": null,
"allowedCidrs": null,
"expiresAt": null,
"createdAt": "2026-10-21T09:12:44.000Z"
},
"member": {
"id": "0d9e4b12-6a3f-4e8c-b7d1-5c2a9f0e3b87",
"name": "Amira Haddad",
"teamIds": []
},
"workspace": {
"id": "a3b5c7d9-1e2f-4a6b-8c0d-2e4f6a8b0c1d",
"name": "Northwind Dental",
"plan": "growth"
},
"apiVersion": "2026-10-21",
"rateLimit": {
"limit": 300,
"remaining": 299,
"resetSeconds": 1,
"workspaceLimit": 600,
"workspaceRemaining": 599
}
}Every response also carries an X-Request-Id header. Quote it if you ever contact support about a
request.
Find the WhatsApp connection to send from
A connection is one connected channel account: a WhatsApp number, an email inbox, a web chat. List them, and pick the WhatsApp one.
curl https://app.gauge.chat/backend/v2/connections \
-H "Authorization: Bearer $GAUGE_API_KEY"Each connection says what it can do over the API right now, with your workspace's settings already applied:
{
"data": [
{
"id": "9b2f6c1e-3d4a-4e5b-8f70-1a2b3c4d5e6f",
"kind": "whatsapp_cloud",
"displayName": "+44 20 7946 0958",
"status": "active",
"createdAt": "2026-09-02T14:03:11.000Z",
"capabilities": {
"sendText": true,
"sendMedia": true,
"sendTemplates": true,
"sendInteractive": false,
"quotedReplies": false,
"startConversations": true,
"broadcast": true,
"delivery": "queued"
},
"flags": { "waTemplates": true, "waCloudMedia": true },
"warning": null
}
],
"nextCursor": null,
"prevCursor": null
}startConversations: true on WhatsApp Cloud means you can message someone first, with an
approved template: WhatsApp allows nothing else as a first message. See
The 24-hour window.
Send a WhatsApp message
POST /v2/messages sends on a connection (scope messages:write, a live key). Address it one way:
reply into an existing conversationId, or reach a contactId or a new number (to) on a
connection that can start conversations. On WhatsApp Cloud, the first message to someone must be
an approved template (next step); the example below replies into a conversation the customer
started.
Every POST needs an Idempotency-Key: if your request times out, retry with the same key and
Gauge sends the message once.
curl https://app.gauge.chat/backend/v2/messages \
-H "Authorization: Bearer $GAUGE_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: order-1042-confirmation" \
-d '{
"connectionId": "9b2f6c1e-3d4a-4e5b-8f70-1a2b3c4d5e6f",
"conversationId": "c41e7b2a-5d6f-4e8a-9b1c-3d5e7f9a1b2c",
"text": "Your appointment is confirmed for Tuesday at 10:30."
}'The answer is { message, conversationId, status, warnings }. 202 Accepted with
status: queued is the normal answer on WhatsApp: the message is saved and leaves right after the
request returns, so it is not yet sent. Its progress (sent, delivered, read, or failed with
a reason) arrives as message.status_updated events. A
channel that sends during the request answers 201 with status: sent.
More than 24 hours after the customer's last message, free text is refused with
422 unsupported_channel_action and reason outside_24h_window; send an approved
template instead.
Message a customer first, with a template
To reach someone who has not written to you, send an approved template with to (an E.164 number)
or contactId. Find the template's name, language and variables with
GET /v2/templates?connectionId=…&status=approved.
curl https://app.gauge.chat/backend/v2/messages \
-H "Authorization: Bearer $GAUGE_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: order-1042-reminder" \
-d '{
"connectionId": "9b2f6c1e-3d4a-4e5b-8f70-1a2b3c4d5e6f",
"to": "+447700900123",
"template": {
"name": "appointment_reminder",
"language": "en_GB",
"variables": { "1": "Layla", "2": "Tuesday 22 October", "3": "10:30" }
}
}'Gauge creates the contact and the conversation (or reuses them), sends the template and answers
with the conversationId. When the customer replies, the window opens and free text works there.
See Start a conversation with a template.
Receive replies by webhook
When the customer answers, Gauge can POST the message to your server.
- Open Developers → Webhooks and choose Add endpoint.
- Enter your HTTPS URL and subscribe to
message.received. - Copy the signing secret. It is shown once, like a key.
- Choose Send test event to check that your endpoint answers
2xx.
Your endpoint must verify the signature before it trusts the body. Here is a complete receiver in Node; Verify signatures has Python and PHP, and every detail.
import crypto from 'node:crypto';
import express from 'express';
const app = express();
const SECRET = process.env.GAUGE_WEBHOOK_SECRET;
// Verify against the RAW body: re-serialised JSON would not match the signature.
app.post('/gauge/webhooks', express.raw({ type: 'application/json' }), (req, res) => {
if (!verifyGaugeSignature(req.headers, req.body, SECRET)) return res.sendStatus(400);
const event = JSON.parse(req.body);
res.sendStatus(204); // answer fast; do the work after
handle(event).catch(console.error);
});
app.listen(3000);Copy verifyGaugeSignature from Verify signatures. Then read
Forward inbound messages for retries, deduplication and ordering.
Next
- Authentication and keys: scopes, test keys, rotation.
- Conventions: errors, idempotency, pagination and rate limits, which apply to every call.
- Channels: what each channel can and cannot do over the API.
The Gauge API
Send and receive customer messages on WhatsApp, email and web chat, keep contacts in sync, and get every event at your own endpoint.
Authentication and keys
Bearer API keys, scopes, live and test environments, App pinning, IP allowlists, expiry, rotation, and what happens when a key's owner leaves.