Support APIQuick starts by stack
Quick start: Express
Node ≥ 18. About 15 minutes from npm install to a verified chat message.
npm install express @gauge/support
export GAUGE_APP_ID=<app id> GAUGE_IDENTITY_SECRET=<identity secret> GAUGE_WEBHOOK_SECRET=<whsec_…>1. Token endpoint
Your session middleware has already put the user on req.user.
import { mintIntegrationToken } from '@gauge/support';
export async function gaugeToken(req, res) {
const token = await mintIntegrationToken(process.env.GAUGE_IDENTITY_SECRET, {
appId: process.env.GAUGE_APP_ID,
userId: String(req.user.id),
integration: 'customer',
name: req.user.name,
email: req.user.email,
});
res.set('cache-control', 'no-store').json({ token });
}2. The widget (your page)
<script src="https://widget.gauge.chat/v1/<version>/widget.js"
integrity="sha384-<integrity>" crossorigin="anonymous" async></script>
<script>
window.addEventListener('load', function () {
window.PulseWebchat.init({
apiUrl: 'https://app.gauge.chat/backend',
connectionId: '<chat connection id>',
supportMode: true,
integration: 'customer',
getToken: function () { // called on every open, so the token is always fresh
return fetch('/gauge-token', { credentials: 'include' })
.then(function (r) { return r.json(); })
.then(function (j) { return j.token; });
},
});
});
</script>CSP: script-src https://widget.gauge.chat and connect-src https://app.gauge.chat wss://app.gauge.chat.
Signed-out visitors: leave out getToken; they chat anonymously where the Integration allows it.
Check my site (Developers → Support) fetches your page and tells you if the snippet, its
integrity and the connection id are right.
3. Webhook
The signature covers the raw bytes, so this route takes express.raw, not express.json.
import { verifyWebhook } from '@gauge/support';
const handled = new Set(); // use your database in production: ids repeat on retries and resends
export async function gaugeWebhook(req, res) {
const result = await verifyWebhook(process.env.GAUGE_WEBHOOK_SECRET, req.body, req.headers);
if (!result.valid) return res.status(400).send(result.reason);
const event = result.event;
if (handled.has(event.id)) return res.sendStatus(200);
handled.add(event.id);
console.info('gauge', event.event, event.id, event.livemode ? 'live' : 'sandbox');
// event.event is the type, event.payload the ids: e.g. push the user on support.chat.message_created
res.sendStatus(200);
}Wire both:
import express from 'express';
import { gaugeToken } from './gauge-token.js';
import { gaugeWebhook } from './gauge-webhook.js';
const app = express();
app.get('/gauge-token', requireLogin, gaugeToken); // your auth
app.post('/gauge/webhooks', express.raw({ type: 'application/json' }), gaugeWebhook);
app.listen(3000);4. Check it
- Sign in to your site as a test user (in the sandbox: Seed test customers, then sign in as
test_customer_1), open the widget and send "hello". In the console the conversation shows the user's name and Verified. Not verified? Paste the JSON from/gauge-tokeninto Developers → Support → Token checker: it names the rule that failed. - Developers → Webhooks → your endpoint → Send test event, pick
support.chat.message_created: the result says Delivered · 200 and your log shows the event id. Change one byte of the secret in your env and send again: your handler answers 400bad_signature.
Server was down? Replay failed on the same page resends everything that did not land.