@wasapi/js-sdk
v2.0.3
Published
SDK oficial en JavaScript (Typescript) para Wasapi.
Downloads
251
Readme
@wasapi/js-sdk
Official Wasapi SDK to quickly integrate with WhatsApp, campaigns, contacts, flows and more.
🚀 Installation
npm install @wasapi/js-sdk
# or
yarn add @wasapi/js-sdk📦 Import
import { WasapiClient } from '@wasapi/js-sdk'⚡ Quick Start
1. Client with from_id (Recommended for production)
import { WasapiClient } from '@wasapi/js-sdk'
const client = new WasapiClient({
apiKey: API_KEY,
from_id: 123456, // Your WhatsApp number ID in Wasapi
})
// Validate connection
const isValid = await client.validateConnection()
if (isValid) {
console.log('✅ Connection successful')
} else {
console.log('❌ Connection error')
}2. Client without from_id (For specific cases)
import { WasapiClient } from '@wasapi/js-sdk'
// Option A: API key only
const client = new WasapiClient(API_KEY)
// Option B: With custom configuration
const client = new WasapiClient({
apiKey: API_KEY,
baseURL: 'https://api-ws.wasapi.io/api/v1' // Optional
})
// You'll need to specify from_id in each request💬 Usage Examples
Send Simple Message
const result = await client.whatsapp.sendMessage({
wa_id: '57300XXXXXXX',
message: 'Hello! 👋'
// from_id is automatically taken from client
})Contacts that hide their phone number ✨ New
Meta lets WhatsApp users hide their phone number. Those contacts arrive without a phone and are identified by two fields the API now returns and accepts:
| Field | What it is |
|-------|------------|
| bsuid | Business-Scoped User ID assigned by Meta, format XX.<alphanumeric>. The technical identifier |
| wa_username | Public WhatsApp username. The human-readable value shown in the chat |
wa_id accepts a phone, a BSUID or a username — the API detects it by format, so an
integration that already sends phone numbers needs no changes.
// All three are equivalent ways to reach the same contact
await client.whatsapp.sendMessage({ wa_id: '57300XXXXXXX', message: 'Hi' })
await client.whatsapp.sendMessage({ bsuid: 'CO.1300484045498206', message: 'Hi' })
await client.whatsapp.sendMessage({ wa_username: 'jpablo.pe', message: 'Hi' })
// Create a contact that hides its number: send bsuid instead of phone
await client.contacts.create({
first_name: 'Juan',
bsuid: 'CO.1300484045498206',
wa_username: 'jpablo.pe'
})Three things to keep in mind:
phonecan benullon the contact and on campaign logs.wa_idis not always a phone. It is the conversation key: for a hidden-number contact it carries the BSUID. To tell the cases apart, checkbsuid !== null && wa_id === bsuid— when that holds, the readable value iswa_username.wa_usernameis mutable and reassignable. Use it to find a contact, never as a primary key — use the contact'suuidfor that.
Send Template
import { SendTemplate } from '@wasapi/js-sdk/models'
const template: SendTemplate = {
recipients: '57300XXXXXXX',
template_id: 'TEMPLATE_UUID',
chatbot_status: 'enable',
conversation_status: 'unchanged'
// contact_type is optional: each recipient is auto-detected by format, and the
// response includes `resolved_as` so you can verify how it was interpreted.
// Pass it explicitly to force an interpretation — `phone` is the only way to
// message a number that is not in your contact list.
}
const sent = await client.whatsapp.sendTemplate(template)Send Attachment
const result = await client.whatsapp.sendAttachment({
wa_id: '57300XXXXXXX',
filePath: 'https://example.com/image.jpg',
caption: 'Test image',
filename: 'image.jpg'
})List Conversations
// All conversations (cursor-based pagination)
const res = await client.conversations.getAll({ per_page: 20 })
// Filter by status
const open = await client.conversations.getAll({ status: 'open' })
// Search by name
const search = await client.conversations.getAll({ query: 'John' })
// Next page using cursor
if (res.pagination.has_more) {
const next = await client.conversations.getNextPage(res.pagination.next_cursor!)
}🔧 Client Configuration
interface WasapiConfig {
apiKey: string; // Your Wasapi API key (required)
from_id?: number; // Your WhatsApp number ID (recommended)
baseURL?: string; // API base URL (optional)
}
const client1 = new WasapiClient(API_KEY) // API key only
const client2 = new WasapiClient({ apiKey: API_KEY, from_id: 123 }) // With config📚 Available Modules
💬 whatsapp
Manage WhatsApp messages, templates, attachments and flows.
| Method | Description |
|--------|-------------|
| sendMessage({ from_id, wa_id \| bsuid \| wa_username, message }) | Send a text message |
| sendAttachment({ from_id, wa_id \| bsuid \| wa_username, filePath, caption?, filename? }) | Send image, video, document or audio |
| sendTemplate({ recipients, template_id, contact_type?, from_id, ... }) | Send a template (up to 20 recipients) |
| sendContacts({ wa_id, from_id, contacts }) | Send contact cards |
| sendFlow({ wa_id, phone_id, flow_id, cta, screen, message }) | Send a WhatsApp Flow |
| getConversation({ wa_id, from_id?, page? }) | Load conversation history |
| getMessageDetail(identifier, { include_contact? }) ✨ | Get one message by wam_id or internal id, with Meta's error_code/error_message on failure |
| getWhatsappNumbers() | List WhatsApp lines on the account |
| getWhatsappTemplates({ phone_id? }) | List templates, optionally filtered by line |
| getWhatsappTemplate({ template_uuid }) | Get a template by UUID |
| getTemplateVariables(template_uuid) ✨ | Variables the template requires (body/header/buttons/media) |
| getTemplatesByAppId({ from_id }) | Get templates for a specific line |
| syncMetaTemplates() | Sync templates from Meta |
| changeStatus({ from_id, wa_id, status, message?, ... }) | Change conversation status or transfer to agent |
| getFlows() | List all WhatsApp Flows |
| getFlowsByPhoneId(from_id?) | Get published flows for a phone line |
| getFlowResponses({ flow_id, page, per_page }) | Get flow responses |
| getFlowAssets({ flow_id, phone_id? }) | Get flow assets |
| getFlowScreens({ flow_id, phone_id? }) | Get flow screens |
📋 conversations ✨ New in v2.0.0
List, search and filter conversations with cursor-based pagination.
| Method | Description |
|--------|-------------|
| getAll(params?) | List/filter conversations |
| getNextPage(cursor, params?) | Navigate to next page |
getAll parameters:
| Param | Type | Description |
|-------|------|-------------|
| query | string | Search term — activates search mode |
| search_type | 'contactName' \| 'all' | Search scope |
| status | 'open' \| 'hold' \| 'closed' | Filter by conversation state |
| phones | string | Comma-separated WhatsApp line IDs |
| labels | string | Comma-separated label IDs |
| agents | string | Comma-separated agent IDs |
| dates | string | Date range YYYY-MM-DD,YYYY-MM-DD |
| without_labels | boolean | Only conversations without labels |
| cursor | string | Pagination cursor |
| per_page | number | Results per page (1–50, default 20) |
Each conversation carries bsuid and wa_username alongside wa_id — see
Contacts that hide their phone number.
👥 contacts
Full contact lifecycle management.
| Method | Description |
|--------|-------------|
| getAll() | List all contacts (paginated) |
| getSearch({ search?, labels?, page? }) | Search contacts |
| getById(wa_id) | Get contact by phone, uuid, bsuid or wa_username |
| create({ first_name, phone \| bsuid, wa_username?, ... }) | Create a contact |
| update({ wa_id, data }) | Update a contact |
| delete(wa_id) | Delete a contact |
| addLabel({ contact_uuid, label_id }) | Add label to contact |
| removeLabel({ contact_uuid, label_id }) | Remove label from contact |
| assingAgentAutomatic({ contact_uuid }) | Auto-assign agent to contact |
| export({ emails }) | Export contacts by email (max 5 emails) |
🏷️ labels
Tag and categorize contacts.
| Method | Description |
|--------|-------------|
| getAll() | List all labels |
| getById(id) | Get label by ID |
| getSearch(name) | Search label by name |
| create({ title, description, color }) | Create a label |
| update({ id, data }) | Update a label |
| delete(id) | Delete a label |
📊 campaigns
Manage messaging campaigns.
| Method | Description |
|--------|-------------|
| getAll() | List all campaigns (legacy, unpaginated) |
| list({ per_page?, cursor? }) ✨ | List campaigns with cursor pagination (1–50, default 20) |
| getById(campaign_uuid) | Get campaign by UUID, with its jobs |
| create(data) | Create and dispatch a campaign |
| getStats(campaign_uuid) | Delivery counts per status |
| getLogs(campaign_uuid, { per_page?, cursor? }) | Per-contact delivery log |
Prefer list() over getAll(): it uses keyset pagination, so it stays fast on large
accounts and does not drift when campaigns are created concurrently.
// Walk every campaign, page by page
let cursor: string | undefined
do {
const page = await client.campaigns.list({ per_page: 50, cursor })
page.data.forEach(c => console.log(c.uuid, c.status, c.total_contacts))
cursor = page.pagination.next_cursor ?? undefined
} while (cursor)Creating a campaign — check what the template needs first:
const vars = await client.whatsapp.getTemplateVariables('TEMPLATE_UUID')
console.log(vars.data.body.variables) // how many {{n}} the body has
console.log(vars.data.header.type) // 'none' | 'text' | 'media'
const campaign = await client.campaigns.create({
name: 'Black Friday 2026',
template_uuid: 'TEMPLATE_UUID',
phone_id: 13,
recipients: { type: 'labels', values: [116, 120] },
variables: { body: ['Carlos', 'Wasapi'] },
scheduled_at: '2026-12-01 09:00', // omit to send immediately
conversation_status: 'closed' // optional, defaults to 'closed'
})
console.log(campaign.data.uuid, campaign.recipients.matched)
console.log(campaign.recipients.skipped) // phones that matched no contact🌀 funnels
Manage sales funnels and stages.
| Method | Description |
|--------|-------------|
| getAll() | List all funnels |
| searchContact({ phoneNumber?, contactUuid? }) | Find contact in funnels |
| moveContactToFunnel({ funnelContactId, toStageId }) | Move contact to a funnel stage |
🔧 customFields
Configure custom fields for contacts.
| Method | Description |
|--------|-------------|
| getAll() | List all custom fields |
| create({ name }) | Create a custom field |
| update({ id, data }) | Update a custom field |
| delete(id) | Delete a custom field |
🤖 bot
Control the chatbot per contact.
| Method | Description |
|--------|-------------|
| toggleStatus({ wa_id, data }) | Enable or disable bot for a contact |
📈 metrics
Dashboard metrics and statistics.
| Method | Description |
|--------|-------------|
| getOnlineAgents() | Agents currently online |
| getTotalCampaigns({ startDate, endDate }) | Total campaigns in range |
| getConsolidatedConversations({ startDate, endDate }) | Conversations by status |
| getAgentConversations({ startDate, endDate }) | Conversations per agent |
| getStatusContacts() | Contact status breakdown |
| getMessages({ startDate, endDate }) | Message volume (in/out) |
| getMessagesBot({ startDate, endDate }) | Bot message volume |
| getAgentTimeResponse({ agentId, startDate, endDate }) | Agent response time |
| getAgentTransferred({ agentId, startDate, endDate }) | Transferred conversations |
| getAgentVolumeOfWork({ agentId, startDate, endDate }) | Agent workload volume |
| getAgentTimeInConversation({ agentId, startDate, endDate }) | Time in conversation |
📑 reports ✨ New in v2.0.0
Performance and satisfaction reports.
| Method | Description |
|--------|-------------|
| getPerformanceByAgent({ start_date, end_date }) | Agent performance report |
| getVolumeOfWorkflow({ start_date, end_date }) | Workflow volume by hour |
| getSatisfactionSurvey({ start_date?, end_date?, whatsapp_number_id? }) | Satisfaction survey report (defaults to the last 30 days) |
⚠️ Totals and averages in
performance-by-agentandvolume-of-workflowcome back as strings, not numbers — the API returns them straight from the SQL aggregate.
// Example
const report = await client.reports.getSatisfactionSurvey({
start_date: '2025-01-01',
end_date: '2025-06-30'
})
console.log(report.data.summary.avg_rating) // Average rating
console.log(report.data.ratings_distribution) // Distribution 1–5⚙️ workflow
Query workflow status history.
| Method | Description |
|--------|-------------|
| getStatuses({ action?, phone?, agent_id?, dates?, per_page?, page? }) | List workflow status events |
👤 user
Account user information.
| Method | Description |
|--------|-------------|
| getUser() | Get authenticated user data |
📋 Requirements
- Node.js >= 18
- Wasapi API Key
🔗 Links
- 📦 NPM Package
- 🐛 Issues
- 🌐 Wasapi
⭐ ¡Dale una estrella a este repositorio si te resulta útil! ⭐
Desarrollado con ❤️ por Juan Camilo Alvarez
