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:read and messages: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"
200 OK
{
  "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.

  1. Open Developers → Webhooks and choose Add endpoint.
  2. Enter your HTTPS URL and subscribe to message.received.
  3. Copy the signing secret. It is shown once, like a key.
  4. 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.

server.js
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

On this page