Node.js Examples
Complete examples for integrating GB Chat API with Node.js applications.
Installation
No SDK required - use the built-in fetch or any HTTP library:
# Optional: Install axios for easier HTTP requests
npm install axios
Basic Setup
Using Fetch (Node.js 18+)
const GBCHAT_API_KEY = process.env.GBCHAT_API_KEY;
const BASE_URL = 'https://inboxapi.workmatic.in/api/v1';
async function sendMessage(to, template, language, variables = {}) {
const response = await fetch(`${BASE_URL}/message/send`, {
method: 'POST',
headers: {
'X-API-Key': GBCHAT_API_KEY,
'Content-Type': 'application/json',
},
body: JSON.stringify({
to,
template,
language,
variables,
}),
});
const data = await response.json();
if (!data.success) {
throw new Error(`${data.error.code}: ${data.error.message}`);
}
return data.data;
}
// Usage
const result = await sendMessage(
'919876543210',
'order_confirmation',
'en',
{ '1': 'John Doe', '2': 'ORD-12345' }
);
console.log('Message sent:', result.messageId);
Using Axios
const axios = require('axios');
const gbchat = axios.create({
baseURL: 'https://inboxapi.workmatic.in/api/v1',
headers: {
'X-API-Key': process.env.GBCHAT_API_KEY,
'Content-Type': 'application/json',
},
});
async function sendMessage(to, template, language, variables = {}, externalId = null) {
try {
const { data } = await gbchat.post('/message/send', {
to,
template,
language,
variables,
externalId,
});
return data.data;
} catch (error) {
if (error.response) {
const { code, message } = error.response.data.error;
throw new Error(`${code}: ${message}`);
}
throw error;
}
}
Complete API Client
// gbchat-client.js
const axios = require('axios');
class GBChatClient {
constructor(apiKey, options = {}) {
this.client = axios.create({
baseURL: options.baseURL || 'https://inboxapi.workmatic.in/api/v1',
headers: {
'X-API-Key': apiKey,
'Content-Type': 'application/json',
},
timeout: options.timeout || 30000,
});
}
async sendMessage({ to, template, language, variables = {}, externalId = null, accountId = null }) {
const payload = {
to: this.normalizePhone(to),
template,
language,
variables,
};
if (externalId) payload.externalId = externalId;
if (accountId) payload.accountId = accountId;
const { data } = await this.client.post('/message/send', payload);
if (!data.success) {
throw new GBChatError(data.error.code, data.error.message);
}
return data.data;
}
normalizePhone(phone) {
// Remove + prefix if present
return phone.replace(/^\+/, '');
}
}
class GBChatError extends Error {
constructor(code, message) {
super(message);
this.code = code;
this.name = 'GBChatError';
}
}
module.exports = { GBChatClient, GBChatError };
Usage
const { GBChatClient, GBChatError } = require('./gbchat-client');
const client = new GBChatClient(process.env.GBCHAT_API_KEY);
async function sendOrderConfirmation(order) {
try {
const result = await client.sendMessage({
to: order.customerPhone,
template: 'order_confirmation',
language: 'en',
variables: {
'1': order.customerName,
'2': order.orderId,
'3': order.total,
},
externalId: order.orderId,
});
console.log('Message sent:', result.messageId);
return result;
} catch (error) {
if (error instanceof GBChatError) {
console.error(`GB Chat Error [${error.code}]: ${error.message}`);
}
throw error;
}
}
Express Webhook Handler
const express = require('express');
const crypto = require('crypto');
const app = express();
app.use(express.json());
const WEBHOOK_SECRET = process.env.GBCHAT_WEBHOOK_SECRET;
// Verify webhook signature
function verifySignature(req) {
const signature = req.headers['x-gbchat-signature'];
const timestamp = req.headers['x-gbchat-timestamp'];
const body = JSON.stringify(req.body);
// Check timestamp (5 minute window)
const currentTime = Math.floor(Date.now() / 1000);
if (Math.abs(currentTime - parseInt(timestamp)) > 300) {
return false;
}
// Verify signature
const expectedSignature = 'sha256=' + crypto
.createHmac('sha256', WEBHOOK_SECRET)
.update(`${timestamp}.${body}`)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expectedSignature)
);
}
// Webhook endpoint
app.post('/webhook/gbchat', async (req, res) => {
// Verify signature
if (!verifySignature(req)) {
console.error('Invalid webhook signature');
return res.status(401).json({ error: 'Invalid signature' });
}
// Respond immediately
res.status(200).send('OK');
// Process webhook asynchronously
try {
await handleWebhook(req.body);
} catch (error) {
console.error('Webhook processing error:', error);
}
});
async function handleWebhook(payload) {
const { event, data } = payload;
console.log(`Received webhook: ${event}`, {
messageId: data.messageId,
externalId: data.externalId,
status: data.status,
});
switch (event) {
case 'message.sent':
await updateOrderStatus(data.externalId, 'notification_sent');
break;
case 'message.delivered':
await updateOrderStatus(data.externalId, 'notification_delivered');
break;
case 'message.read':
await updateOrderStatus(data.externalId, 'notification_read');
break;
case 'message.failed':
await handleFailedMessage(data);
break;
case 'webhook.test':
console.log('Test webhook received successfully');
break;
default:
console.log('Unknown event:', event);
}
}
async function updateOrderStatus(orderId, status) {
// Update your database
console.log(`Updating order ${orderId} status to ${status}`);
}
async function handleFailedMessage(data) {
console.error('Message failed:', {
messageId: data.messageId,
error: data.error,
});
// Send alert, retry, or take other action
}
app.listen(3000, () => {
console.log('Webhook server listening on port 3000');
});
Batch Sending with Rate Limiting
const { GBChatClient } = require('./gbchat-client');
const client = new GBChatClient(process.env.GBCHAT_API_KEY);
async function sendBatch(messages, rateLimit = 60) {
const results = [];
const delay = 60000 / rateLimit; // ms between messages
for (let i = 0; i < messages.length; i++) {
const message = messages[i];
try {
const result = await client.sendMessage(message);
results.push({ success: true, ...result });
console.log(`Sent ${i + 1}/${messages.length}: ${result.messageId}`);
} catch (error) {
results.push({
success: false,
to: message.to,
error: error.message,
});
console.error(`Failed ${i + 1}/${messages.length}: ${error.message}`);
}
// Wait between messages (except for the last one)
if (i < messages.length - 1) {
await new Promise(resolve => setTimeout(resolve, delay));
}
}
return results;
}
// Usage
const messages = [
{ to: '919876543210', template: 'promo', language: 'en', variables: { '1': 'Alice' } },
{ to: '919876543211', template: 'promo', language: 'en', variables: { '1': 'Bob' } },
{ to: '919876543212', template: 'promo', language: 'en', variables: { '1': 'Charlie' } },
];
const results = await sendBatch(messages);
console.log('Batch complete:', results);
TypeScript Support
// types.ts
export interface SendMessageRequest {
to: string;
template: string;
language: string;
variables?: Record<string, string>;
externalId?: string;
accountId?: string;
}
export interface SendMessageResponse {
messageId: string;
waMessageId: string;
status: 'sent';
to: string;
template: string;
externalId?: string;
}
export interface WebhookPayload {
event: 'message.sent' | 'message.delivered' | 'message.read' | 'message.failed' | 'webhook.test';
timestamp: number;
data: {
messageId: string;
externalId?: string;
status: string;
waMessageId?: string;
to?: string;
template?: string;
error?: {
code: string;
message: string;
};
};
}
// gbchat-client.ts
import axios, { AxiosInstance } from 'axios';
import { SendMessageRequest, SendMessageResponse } from './types';
export class GBChatClient {
private client: AxiosInstance;
constructor(apiKey: string) {
this.client = axios.create({
baseURL: 'https://inboxapi.workmatic.in/api/v1',
headers: {
'X-API-Key': apiKey,
'Content-Type': 'application/json',
},
});
}
async sendMessage(request: SendMessageRequest): Promise<SendMessageResponse> {
const { data } = await this.client.post('/message/send', request);
if (!data.success) {
throw new Error(`${data.error.code}: ${data.error.message}`);
}
return data.data;
}
}