tabi-sdk
v0.2.0
Published
Official JavaScript/TypeScript SDK for the Tabi WhatsApp business messaging API
Downloads
601
Maintainers
Readme
tabi-sdk
Official JavaScript / TypeScript SDK for the Tabi WhatsApp Business Messaging API.
Table of Contents
- Installation
- Getting Started
- Configuration
- Resource groups
- Resources
- Error Handling
- TypeScript Support
- Requirements
- License
Installation
# npm
npm install tabi-sdk
# yarn
yarn add tabi-sdk
# pnpm
pnpm add tabi-sdkGetting Started
import { TabiClient } from 'tabi-sdk';
const tabi = new TabiClient({
apiKey: 'tk_your_api_key',
baseUrl: 'https://api.tabi.africa/api/v1',
});
// Send a WhatsApp message
const result = await tabi.messages.send('your-channel-id', {
to: '2348012345678',
content: 'Hello from the Tabi SDK!',
});
console.log(result);Where to find your credentials:
| Value | Location |
|-------|----------|
| apiKey | Dashboard → Developer → API Keys → Create key |
| baseUrl | Always https://api.tabi.africa/api/v1 |
| channelId | Dashboard → Channels → click a channel → copy the ID from the URL |
Configuration
const tabi = new TabiClient({
apiKey: 'tk_...', // required — your API key or JWT access token
baseUrl: 'https://api.tabi.africa/api/v1', // required — API base URL
});Resource groups (feature areas)
The SDK mirrors how the Tabi API is organised in the docs. Each property on TabiClient maps to one REST area.
| Group | tabi.<property> | What it covers |
|--------|-------------------|----------------|
| Getting started | auth, workspaces | Login/register/tokens; workspaces, members, invites |
| Messaging & inbox | channels, messages, conversations, contacts, quickReplies, notifications | WhatsApp lines, sends, threads, people, shortcuts |
| Automations & campaigns | automationTemplates, automationInstalls, campaigns | Template catalog, installed flows, broadcasts |
| Integrations | apiKeys, webhooks, integrations | Keys (create with JWT), outbound webhooks, third-party links |
| Media & insights | files, analytics | Uploads, KPIs |
In TypeScript you can also import the same structure as data (e.g. for building internal tooling or docs UI):
import { SDK_RESOURCE_GROUPS } from 'tabi-sdk';
for (const g of SDK_RESOURCE_GROUPS) {
console.log(g.title, g.members.map((m) => m.property));
}Resources
Auth
Manage authentication — login, register, refresh tokens, and fetch the current user profile.
// Login
const session = await tabi.auth.login('[email protected]', 'password');
// Register a new account
const account = await tabi.auth.register({
email: '[email protected]',
password: 'securePassword',
firstName: 'John',
lastName: 'Doe',
workspaceName: 'My Company',
});
// Refresh an access token
const tokens = await tabi.auth.refresh('your-refresh-token');
// Get current user + workspace entitlements
const me = await tabi.auth.me();
// Logout
await tabi.auth.logout();Channels
Create, list, connect, and manage WhatsApp channels.
// List all channels
const channels = await tabi.channels.list();
// Get a specific channel
const channel = await tabi.channels.get('channel-id');
// Create a new channel
const newChannel = await tabi.channels.create({
name: 'Support Line',
provider: 'go-whatsapp',
});
// Connect a channel (start the WhatsApp session)
await tabi.channels.connect('channel-id');
// Check channel status
const status = await tabi.channels.status('channel-id');
// Disconnect a channel
await tabi.channels.disconnect('channel-id');
// Delete a channel
await tabi.channels.delete('channel-id');
// Update settings (name, caps, risk engine) — requires user JWT, not a channel API key
await tabi.channels.update('channel-id', { riskEngineEnabled: false });
// Ask gateway to reconnect the session — JWT only
await tabi.channels.reconnect('channel-id');Messages
Send text messages, media, stickers, locations, polls, and manage message actions.
// Send a text message
await tabi.messages.send('channel-id', {
to: '2348012345678',
content: 'Hello! How can we help you today?',
});
// Send an image message
await tabi.messages.send('channel-id', {
to: '2348012345678',
content: 'Check this out!',
messageType: 'image',
mediaUrl: 'https://example.com/image.png',
});
// Send a document
await tabi.messages.send('channel-id', {
to: '2348012345678',
content: 'Here is your invoice',
messageType: 'document',
mediaUrl: 'https://example.com/invoice.pdf',
});
// Get a specific message
const msg = await tabi.messages.get('message-id');
// List messages in a conversation
const timeline = await tabi.messages.listByConversation('conversation-id', {
page: 1,
limit: 50,
});
// Reply in a conversation thread
await tabi.messages.reply('conversation-id', {
content: 'Thanks for reaching out!',
});
// Send a poll
await tabi.messages.sendPoll('channel-id', {
to: '2348012345678',
question: 'What do you prefer?',
options: ['Option A', 'Option B', 'Option C'],
maxAnswer: 1,
});
// Send a location
await tabi.messages.sendLocation('channel-id', {
to: '2348012345678',
latitude: 6.5244,
longitude: 3.3792,
});
// Send a contact card
await tabi.messages.sendContact('channel-id', {
to: '2348012345678',
contactName: 'Jane Doe',
contactPhone: '2348099999999',
});
// React to a message
await tabi.messages.react('channel-id', 'provider-msg-id', {
emoji: '👍',
});
// Mark a message as read
await tabi.messages.markRead('channel-id', 'provider-msg-id');
// Edit a sent message
await tabi.messages.edit('channel-id', 'provider-msg-id', {
content: 'Updated message text',
});
// Revoke (unsend) a message
await tabi.messages.revoke('channel-id', 'provider-msg-id');
// Download media from a message
const media = await tabi.messages.downloadMedia('channel-id', 'provider-msg-id');Contacts
Create, update, import contacts, manage tags and consent.
// List contacts (with pagination & search)
const contacts = await tabi.contacts.list({ page: 1, limit: 20, search: 'John' });
// Get a single contact
const contact = await tabi.contacts.get('contact-id');
// Create a contact
const newContact = await tabi.contacts.create({
phone: '2348012345678',
firstName: 'John',
lastName: 'Doe',
email: '[email protected]',
});
// Update a contact
await tabi.contacts.update('contact-id', { firstName: 'Jonathan' });
// Delete a contact
await tabi.contacts.delete('contact-id');
// Bulk import contacts
await tabi.contacts.import({
contacts: [
{ phone: '2348012345678', firstName: 'Alice' },
{ phone: '2348087654321', firstName: 'Bob' },
],
});
// Tag management
const tags = await tabi.contacts.getTags('contact-id');
await tabi.contacts.addTag('contact-id', 'vip');
await tabi.contacts.removeTag('contact-id', 'vip');
// Consent management
await tabi.contacts.optIn('contact-id');
await tabi.contacts.optOut('contact-id');Conversations
Manage inbox conversations — list, update, resolve, and reopen.
// List conversations
const convos = await tabi.conversations.list({ page: 1, limit: 25, status: 'open' });
// Get a single conversation
const convo = await tabi.conversations.get('conversation-id');
// Update conversation metadata
await tabi.conversations.update('conversation-id', {
assignedTo: 'member-id',
});
// Resolve a conversation
await tabi.conversations.resolve('conversation-id');
// Reopen a resolved conversation
await tabi.conversations.reopen('conversation-id');
// Mark a conversation as read
await tabi.conversations.markRead('conversation-id');Webhooks
Subscribe to real-time events, inspect delivery logs, and test payloads.
// Create a webhook subscription
const webhook = await tabi.webhooks.create({
url: 'https://example.com/webhook',
events: ['message.received', 'message.sent', 'conversation.created'],
});
// List all webhooks
const webhooks = await tabi.webhooks.list();
// Get a specific webhook
const wh = await tabi.webhooks.get('webhook-id');
// Update a webhook
await tabi.webhooks.update('webhook-id', {
url: 'https://example.com/new-webhook',
events: ['message.received'],
});
// Ping a webhook (send a test payload)
await tabi.webhooks.ping('webhook-id');
// Rotate the webhook signing secret
await tabi.webhooks.rotateSecret('webhook-id');
// View delivery logs
const logs = await tabi.webhooks.deliveryLogs({ page: 1, limit: 50 });
// Test capture (capture webhook payloads for debugging)
await tabi.webhooks.startTestCapture();
const captured = await tabi.webhooks.testCaptureStatus();
await tabi.webhooks.stopTestCapture();
// Delete a webhook
await tabi.webhooks.delete('webhook-id');API Keys
Create and manage API keys for programmatic access. Creating keys requires a user JWT from the dashboard (not an API key). Types: CreateApiKeyPayload, ApiKeyCreatedRecord (exported from tabi-sdk).
| Field | Type | Required | Description |
|--------|------|----------|-------------|
| name | string | yes | Label in the dashboard |
| channelId | string (UUID) | no | Restrict key to one channel |
| scopes | string[] | no | e.g. ['channels:read', 'messages:send']; omit for full access in scope |
| expiresAt | ISO string | no | After this time the key stops working |
import type { CreateApiKeyPayload } from 'tabi-sdk';
const payload: CreateApiKeyPayload = {
name: 'Production Key',
scopes: ['messages:send', 'channels:read'],
// channelId: 'uuid-of-channel', // optional
// expiresAt: '2027-01-01T00:00:00.000Z',
};
const key = await tabi.apiKeys.create(payload);
console.log(key.rawKey); // save immediately — only returned once
// List keys (optional filter)
const keys = await tabi.apiKeys.list({ channelId: 'uuid' });
const all = await tabi.apiKeys.list();
await tabi.apiKeys.revoke('key-id');
await tabi.apiKeys.delete('key-id');Files
Upload and manage files (images, documents, audio, video).
// List uploaded files
const files = await tabi.files.list();
// Get file metadata
const file = await tabi.files.get('file-id');
// Get a temporary download URL
const urlData = await tabi.files.getUrl('file-id');
// Delete a file
await tabi.files.delete('file-id');Campaigns
Create and manage broadcast campaigns.
// Create a campaign
const campaign = await tabi.campaigns.create({
name: 'Promo Blast',
channelId: 'channel-id',
message: { text: 'Flash sale — 50% off today!' },
audienceFilter: { tags: ['subscribers'] },
});
// List campaigns
const campaigns = await tabi.campaigns.list({ page: 1, limit: 10 });
// Get a campaign
const c = await tabi.campaigns.get('campaign-id');
// Update a draft campaign
await tabi.campaigns.update('campaign-id', { name: 'Updated Promo' });
// Lifecycle actions
await tabi.campaigns.schedule('campaign-id');
await tabi.campaigns.pause('campaign-id');
await tabi.campaigns.resume('campaign-id');
await tabi.campaigns.cancel('campaign-id');
// Delete a campaign
await tabi.campaigns.delete('campaign-id');Automation Templates
Browse pre-built automation templates.
// List all templates
const templates = await tabi.automationTemplates.list();
// Get a specific template
const tpl = await tabi.automationTemplates.get('template-id');Automation Installs
Install, configure, and manage automation instances.
// Install an automation from a template
const install = await tabi.automationInstalls.install({
templateId: 'template-id',
channelId: 'channel-id',
config: { greeting: 'Welcome!' },
});
// List installed automations
const installs = await tabi.automationInstalls.list();
// Get a specific install
const inst = await tabi.automationInstalls.get('install-id');
// Update configuration
await tabi.automationInstalls.update('install-id', {
config: { greeting: 'Hi there!' },
});
// Enable / disable
await tabi.automationInstalls.enable('install-id');
await tabi.automationInstalls.disable('install-id');
// Uninstall
await tabi.automationInstalls.uninstall('install-id');Quick Replies
Manage canned responses for fast agent replies.
// List quick replies
const replies = await tabi.quickReplies.list();
// Create a quick reply
await tabi.quickReplies.create({
shortcut: '/hello',
body: 'Hello! How can I help you today?',
});
// Update a quick reply
await tabi.quickReplies.update('reply-id', { body: 'Updated greeting' });
// Delete a quick reply
await tabi.quickReplies.delete('reply-id');Analytics
Retrieve dashboard and reporting data.
// Dashboard overview
const dashboard = await tabi.analytics.dashboard({ from: '2025-01-01', to: '2025-01-31' });
// Channel analytics
const channelStats = await tabi.analytics.channels({ from: '2025-01-01', to: '2025-01-31' });
// Conversation analytics
const convoStats = await tabi.analytics.conversations({ from: '2025-01-01', to: '2025-01-31' });Notifications
Read in-app notifications.
// List notifications
const notifs = await tabi.notifications.list({ page: 1, limit: 20 });
// Mark one as read
await tabi.notifications.markRead('notification-id');
// Mark all as read
await tabi.notifications.markAllRead();
// Get unread count
const count = await tabi.notifications.unreadCount();Integrations
Manage third-party integrations (CRM, helpdesk, etc.).
// List available providers
const providers = await tabi.integrations.listProviders();
// Create an integration
const integration = await tabi.integrations.create({
providerId: 'hubspot',
config: { apiKey: 'hs_...' },
});
// List configured integrations
const integrations = await tabi.integrations.list();
// Test an integration connection
await tabi.integrations.test('integration-id');
// Update integration config
await tabi.integrations.update('integration-id', {
config: { apiKey: 'hs_new_key' },
});
// Delete an integration
await tabi.integrations.delete('integration-id');Workspaces
Manage workspaces and team members.
// List your workspaces
const workspaces = await tabi.workspaces.list();
// Get a workspace
const ws = await tabi.workspaces.get('workspace-id');
// Create a workspace
const newWs = await tabi.workspaces.create({ name: 'New Team' });
// Update workspace settings
await tabi.workspaces.update('workspace-id', { name: 'Renamed Team' });
// List members
const members = await tabi.workspaces.listMembers('workspace-id');
// Invite a team member
await tabi.workspaces.inviteMember('workspace-id', {
email: '[email protected]',
roleSlug: 'admin',
});Error Handling
All API errors throw a TabiError with the HTTP status code and the server's error message.
import { TabiClient, TabiError } from 'tabi-sdk';
const tabi = new TabiClient({ apiKey: 'tk_...', baseUrl: 'https://api.tabi.africa/api/v1' });
try {
await tabi.messages.send('channel-id', { to: '234...', content: 'Hi' });
} catch (err) {
if (err instanceof TabiError) {
console.error('Status:', err.status); // e.g. 400, 401, 403, 404
console.error('Message:', err.message); // human-readable error from the API
console.error('Body:', err.body); // full JSON error response
} else {
throw err; // network error or something unexpected
}
}Common error codes
| Status | Meaning |
|--------|---------|
| 400 | Bad request — check your payload |
| 401 | Unauthorized — invalid or expired API key |
| 403 | Forbidden — insufficient permissions |
| 404 | Not found — resource doesn't exist |
| 409 | Conflict — duplicate or already exists |
| 429 | Rate limited — slow down and retry |
| 500 | Server error — contact support |
TypeScript Support
The SDK is written in TypeScript and ships with full type declarations. You get autocompletion, parameter hints, and type-checking out of the box — no @types package needed.
import { TabiClient, TabiError, type TabiClientOptions } from 'tabi-sdk';Requirements
- Node.js >= 18 (uses the built-in
fetchAPI) - Works with any JavaScript runtime that supports
fetch(Bun, Deno, Cloudflare Workers, etc.)
Source
- Repository: github.com/Tabi-messaging/tabi-sdk-js
- Full stack (web + API): github.com/Tabi-messaging/tabi-full-app-system
License
MIT — see LICENSE for details.
