Skip to main content

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;
}
}