@semboja/connect
v0.4.0
Published
Official Node.js SDK for Semboja WhatsApp API Bridge
Maintainers
Readme
@semboja/connect
Official Node.js SDK for Semboja WhatsApp API Bridge.
Installation
npm install @semboja/connect
# or
yarn add @semboja/connect
# or
pnpm add @semboja/connectQuick Start
import { SembojaClient } from '@semboja/connect';
const client = new SembojaClient('sk_live_your_api_key');
// Send a text message
const result = await client.messages.sendText({
phoneNumberId: '123456789',
to: '+6281234567890',
text: 'Hello from Semboja!',
});
console.log('Message ID:', result.data.messages[0].id);Features
- Type-safe - Full TypeScript support with comprehensive types
- Simple API - Intuitive methods for all WhatsApp operations
- Error handling - Typed errors for easy error handling
- Webhook verification - Built-in signature verification
- Retry logic - Automatic retries with exponential backoff
- Test mode - Safe testing with
sk_test_*keys
Usage
Initialize Client
import { SembojaClient } from '@semboja/connect';
// Simple initialization
const client = new SembojaClient('sk_live_your_api_key');
// With options
const client = new SembojaClient({
apiKey: process.env.SEMBOJA_API_KEY!,
timeout: 60000, // 60 seconds
retries: 5,
});Send Messages
// Text message
await client.messages.sendText({
phoneNumberId: '123456789',
to: '+6281234567890',
text: 'Hello, World!',
previewUrl: true, // Enable URL preview
});
// Reply to a message
await client.messages.sendText({
phoneNumberId: '123456789',
to: '+6281234567890',
text: 'Thanks for your message!',
replyTo: 'wamid.xxx', // Message ID to reply to
});
// Template message
await client.messages.sendTemplate({
phoneNumberId: '123456789',
to: '+6281234567890',
template: {
name: 'order_confirmation',
language: { code: 'id' },
components: [
{
type: 'body',
parameters: [
{ type: 'text', text: 'John' },
{ type: 'text', text: 'ORD-12345' },
],
},
],
},
});
// Image message
await client.messages.sendImage({
phoneNumberId: '123456789',
to: '+6281234567890',
image: {
link: 'https://example.com/image.jpg',
caption: 'Check this out!',
},
});
// Document message
await client.messages.sendDocument({
phoneNumberId: '123456789',
to: '+6281234567890',
document: {
link: 'https://example.com/invoice.pdf',
filename: 'invoice.pdf',
caption: 'Your invoice',
},
});
// Reaction
await client.messages.sendReaction({
phoneNumberId: '123456789',
to: '+6281234567890',
reaction: {
messageId: 'wamid.xxx',
emoji: '👍',
},
});
// Interactive buttons
await client.messages.sendInteractive({
phoneNumberId: '123456789',
to: '+6281234567890',
interactive: {
type: 'button',
body: { text: 'Choose an option:' },
action: {
buttons: [
{ type: 'reply', reply: { id: 'yes', title: 'Yes' } },
{ type: 'reply', reply: { id: 'no', title: 'No' } },
],
},
},
});
// Sticker message
await client.messages.sendSticker({
phoneNumberId: '123456789',
to: '+6281234567890',
sticker: {
link: 'https://example.com/sticker.webp',
},
});
// Location message
await client.messages.sendLocation({
phoneNumberId: '123456789',
to: '+6281234567890',
location: {
latitude: -6.2088,
longitude: 106.8456,
name: 'Monas',
address: 'Gambir, Central Jakarta, Indonesia',
},
});
// Contact card
await client.messages.sendContacts({
phoneNumberId: '123456789',
to: '+6281234567890',
contacts: [
{
name: {
formatted_name: 'John Doe',
first_name: 'John',
last_name: 'Doe',
},
phones: [
{ phone: '+6281234567890', type: 'CELL' },
],
emails: [
{ email: '[email protected]', type: 'WORK' },
],
},
],
});
// Mark message as read
await client.messages.markAsRead({
phoneNumberId: '123456789',
messageId: 'wamid.xxx',
});Templates
// List all templates
const templates = await client.templates.list();
// Filter by status
const approved = await client.templates.list({ status: 'APPROVED' });Phone Numbers
const phoneNumbers = await client.phoneNumbers.list();
for (const phone of phoneNumbers.data) {
console.log(`${phone.verified_name}: ${phone.display_phone_number}`);
}Usage Statistics
const usage = await client.usage.get();
console.log(`Period: ${usage.data.period.start} - ${usage.data.period.end}`);
console.log(`Messages sent: ${usage.data.messages.sent}`);
console.log(`Messages received: ${usage.data.messages.received}`);
console.log(`API calls: ${usage.data.api_calls}`);Test Mode
Use sk_test_* API keys to test without sending real messages:
const client = new SembojaClient('sk_test_your_test_key');
// Check if in test mode
console.log('Test mode:', client.isTestMode); // true
// Trigger a test webhook
await client.test.triggerWebhook({
phoneNumberId: '123456789',
type: 'text',
from: '+6281234567890',
text: 'Test incoming message',
});Webhook Verification
import { verifyWebhookSignature } from '@semboja/connect';
// Express.js example
app.post('/webhook', express.raw({ type: 'application/json' }), (req, res) => {
const isValid = verifyWebhookSignature({
payload: req.body,
signature: req.headers['x-semboja-signature'] as string,
timestamp: req.headers['x-semboja-timestamp'] as string,
secret: process.env.WEBHOOK_SECRET!,
});
if (!isValid) {
return res.status(401).send('Invalid signature');
}
const event = JSON.parse(req.body.toString());
console.log('Received event:', event);
res.status(200).send('OK');
});Error Handling
import {
SembojaClient,
AuthenticationError,
RateLimitError,
ValidationError,
} from '@semboja/connect';
const client = new SembojaClient('sk_live_your_api_key');
try {
await client.messages.sendText({
phoneNumberId: '123456789',
to: '+6281234567890',
text: 'Hello!',
});
} catch (error) {
if (error instanceof AuthenticationError) {
console.error('Invalid API key');
} else if (error instanceof RateLimitError) {
console.error('Rate limited, retry after:', error.resetAt);
} else if (error instanceof ValidationError) {
console.error('Invalid request:', error.message);
} else {
throw error;
}
}API Reference
SembojaClient
| Property | Type | Description |
|----------|------|-------------|
| messages | Messages | Messages API |
| templates | Templates | Templates API |
| phoneNumbers | PhoneNumbers | Phone Numbers API |
| usage | Usage | Usage API |
| test | Test | Test API (test mode only) |
| isTestMode | boolean | Whether using test API key |
Messages API
| Method | Description |
|--------|-------------|
| sendText(options) | Send a text message |
| sendTemplate(options) | Send a template message |
| sendImage(options) | Send an image |
| sendVideo(options) | Send a video |
| sendAudio(options) | Send an audio file |
| sendDocument(options) | Send a document |
| sendSticker(options) | Send a sticker (WebP) |
| sendLocation(options) | Send a location |
| sendContacts(options) | Send contact cards |
| sendReaction(options) | Send a reaction |
| sendInteractive(options) | Send interactive message |
| markAsRead(options) | Mark a message as read |
Error Classes
| Class | Status Code | Description |
|-------|-------------|-------------|
| SembojaError | varies | Base error class |
| AuthenticationError | 401 | Invalid API key |
| RateLimitError | 429 | Rate limit exceeded |
| ValidationError | 400 | Invalid request |
| NotFoundError | 404 | Resource not found |
| ServerError | 500 | Server error |
| NetworkError | - | Network/connection error |
Requirements
- Node.js 20.0.0 or higher
Links
License
MIT - Semboja Tech
