npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

tabi-sdk

v0.2.0

Published

Official JavaScript/TypeScript SDK for the Tabi WhatsApp business messaging API

Downloads

601

Readme

tabi-sdk

Official JavaScript / TypeScript SDK for the Tabi WhatsApp Business Messaging API.

npm version License: MIT


Table of Contents


Installation

# npm
npm install tabi-sdk

# yarn
yarn add tabi-sdk

# pnpm
pnpm add tabi-sdk

Getting 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 fetch API)
  • Works with any JavaScript runtime that supports fetch (Bun, Deno, Cloudflare Workers, etc.)

Source


License

MIT — see LICENSE for details.