TypeScript SDK
The official TypeScript SDK for ZapyAPI provides a type-safe, easy-to-use interface for interacting with your WhatsApp instances.
Installation
npm install @zapyapi/sdk
# or
yarn add @zapyapi/sdk
# or
pnpm add @zapyapi/sdk
Quick Start
import { ZapyClient } from '@zapyapi/sdk';
const client = new ZapyClient({
apiKey: 'your-api-key',
});
// Send a text message
const result = await client.messages.sendText('my-instance', {
to: '5511999999999',
message: 'Hello from ZapyAPI SDK!'
});
console.log('Message sent:', result.messageId);
Client Configuration
import { ZapyClient } from '@zapyapi/sdk';
const client = new ZapyClient({
// Required: Your API key from the dashboard
apiKey: 'your-api-key',
// Optional: Base URL (defaults to production)
baseUrl: 'https://api.zapyapi.com/api',
// Optional: Request timeout in milliseconds (default: 30000)
timeout: 30000,
// Optional: Custom headers
headers: {
'X-Custom-Header': 'value'
}
});
Available Resources
Instances
Manage your WhatsApp instances:
// List all instances
const { data: instances } = await client.instances.list();
// Get QR code for connecting
const qr = await client.instances.getQRCode('my-instance');
console.log('Scan this QR:', qr.qrCode);
// Restart an instance
await client.instances.restart('my-instance');
// Logout an instance
await client.instances.logout('my-instance');
// Check if numbers are on WhatsApp
const result = await client.instances.checkNumbers('my-instance', [
'5511999999999',
'5521888888888'
]);
for (const check of result.results) {
console.log(`${check.number}: ${check.exists ? 'On WhatsApp' : 'Not found'}`);
}
// Send typing indicator
await client.instances.sendPresence('my-instance', {
to: '5511999999999',
presence: 'composing'
});
// Get profile picture
const profile = await client.instances.getProfilePicture('my-instance', '5511999999999');
if (profile.url) {
console.log('Profile picture:', profile.url);
}
// Block/unblock contacts
await client.instances.blockContact('my-instance', '5511999999999');
await client.instances.unblockContact('my-instance', '5511999999999');
// Get group metadata
const group = await client.instances.getGroupMetadata('my-instance', '120363123456789012@g.us');
console.log(`Group: ${group.subject}, Participants: ${group.participants.length}`);
Messages
Send and manage messages:
// Send text message
await client.messages.sendText('my-instance', {
to: '5511999999999',
message: 'Hello!',
quoteMessageId: 'optional-message-id-to-reply'
});
// Send image
await client.messages.sendImage('my-instance', {
to: '5511999999999',
image: 'https://example.com/image.jpg', // URL or base64
caption: 'Check this out!',
viewOnce: false
});
// Send video
await client.messages.sendVideo('my-instance', {
to: '5511999999999',
video: 'https://example.com/video.mp4',
caption: 'Watch this video!'
});
// Send audio note (voice message)
await client.messages.sendAudioNote('my-instance', {
to: '5511999999999',
audio: 'data:audio/ogg;base64,...'
});
// Send audio file
await client.messages.sendAudioFile('my-instance', {
to: '5511999999999',
audio: 'https://example.com/audio.mp3'
});
// Send document
await client.messages.sendDocument('my-instance', {
to: '5511999999999',
document: 'https://example.com/file.pdf',
fileName: 'report.pdf',
caption: 'Here is the report'
});
// Forward a message
await client.messages.forward('my-instance', {
to: '5511999999999',
messageId: 'original-message-id'
});
// Edit a message
await client.messages.edit('my-instance', {
messageId: 'message-id',
message: 'Updated text'
});
// Mark as read
await client.messages.read('my-instance', {
messageId: 'message-id'
});
// Delete a message
await client.messages.delete('my-instance', {
messageId: 'message-id'
});
// Get media download link
const media = await client.messages.getMediaDownloadLink('my-instance', 'message-id');
console.log('Download URL:', media.url);
// Send location
await client.messages.sendLocation('my-instance', {
to: '5511999999999',
latitude: -23.5505,
longitude: -46.6333,
name: 'São Paulo',
address: 'São Paulo, Brazil'
});
// Send contact card
await client.messages.sendContact('my-instance', {
to: '5511999999999',
contact: {
fullName: 'John Doe',
phoneNumber: '+5511988887777',
organization: 'Acme Inc'
}
});
// Send sticker
await client.messages.sendSticker('my-instance', {
to: '5511999999999',
url: 'https://example.com/sticker.webp'
});
// Send reaction
await client.messages.sendReaction('my-instance', {
messageId: 'message-id',
reaction: '👍'
});
// Remove reaction
await client.messages.sendReaction('my-instance', {
messageId: 'message-id',
reaction: ''
});
Enums and Constants
The SDK exports type-safe enums and constants for common values:
import {
ZapyEventTypes,
InstanceStatus,
ZapyMessageStatusEnum,
ZapyMessageType,
WebhookQueueStatus
} from '@zapyapi/sdk';
// Check instance status
if (instance.status === InstanceStatus.CONNECTED) {
console.log('Ready to send messages!');
}
// Handle webhook events
if (payload.event === ZapyEventTypes.MESSAGE) {
console.log('New message received!');
}
// Check message delivery status
if (event.data.status === ZapyMessageStatusEnum.READ) {
console.log('Message was read!');
}
Available Enums
ZapyEventTypes
Event type constants for webhook handling:
ZapyEventTypes.MESSAGE // 'message'
ZapyEventTypes.MESSAGE_STATUS // 'message-status'
ZapyEventTypes.REACTION // 'reaction'
ZapyEventTypes.PRESENCE // 'presence'
ZapyEventTypes.QR_CODE // 'qr-code'
ZapyEventTypes.CONTACT_CREATED // 'contact-created'
ZapyEventTypes.CONTACT_UPDATED // 'contact-updated'
ZapyEventTypes.CONTACT_DEDUPLICATED // 'contact-deduplicated'
ZapyEventTypes.INSTANCE_STATUS // 'instance-status'
InstanceStatus
InstanceStatus.STOPPED // 'stopped'
InstanceStatus.MANUALLY_STOPPED // 'manually_stopped'
InstanceStatus.CONNECTING // 'connecting'
InstanceStatus.PENDING_QR_CODE_SCAN // 'pending_qr_code_scan'
InstanceStatus.CONNECTED // 'connected'
InstanceStatus.ERROR // 'error'
InstanceStatus.CREATED // 'created'
InstanceStatus.QR_TIMEOUT // 'qr_timeout'
InstanceStatus.PAYMENT_PENDING // 'payment_pending'
ZapyMessageStatusEnum
Message delivery status:
ZapyMessageStatusEnum.PENDING // 'PENDING'
ZapyMessageStatusEnum.SENT // 'SENT'
ZapyMessageStatusEnum.RECEIVED // 'RECEIVED'
ZapyMessageStatusEnum.READ // 'READ'
ZapyMessageStatusEnum.PLAYED // 'PLAYED'
ZapyMessageStatusEnum.ERROR // 'ERROR'
ZapyMessageType
Message content types:
ZapyMessageType.TEXT // 'text'
ZapyMessageType.IMAGE // 'image'
ZapyMessageType.VIDEO // 'video'
ZapyMessageType.AUDIO // 'audio'
ZapyMessageType.DOCUMENT // 'document'
ZapyMessageType.STICKER // 'sticker'
ZapyMessageType.LOCATION // 'location'
ZapyMessageType.LIVE_LOCATION // 'live_location'
ZapyMessageType.CONTACT // 'contact'
ZapyMessageType.REACTION // 'reaction'
ZapyMessageType.EDITED // 'edited'
ZapyMessageType.DELETED // 'deleted'
ZapyMessageType.POLL // 'poll'
ZapyMessageType.POLL_VOTE // 'poll_vote'
ZapyMessageType.CALL // 'call'
Webhook Handling
Type Guards
Use built-in type guards for type-safe webhook handling:
import {
ZapyWebhookPayload,
ZapyEventTypes,
ZapyMessageType,
isTextMessage,
isImageMessage,
isVideoMessage,
isAudioMessage,
isMediaMessage
} from '@zapyapi/sdk';
function handleWebhook(payload: ZapyWebhookPayload) {
switch (payload.event) {
case ZapyEventTypes.MESSAGE:
// Handle incoming message
const message = payload.data;
console.log('From:', message.sender.name);
// Use type guards to check message type
if (isTextMessage(message)) {
console.log('Text:', message.text);
} else if (isImageMessage(message)) {
console.log('Image caption:', message.caption);
} else if (isMediaMessage(message)) {
console.log('Media type:', message.messageType);
}
break;
case ZapyEventTypes.MESSAGE_STATUS:
// Handle message status update
console.log('Message ID:', payload.data.id);
console.log('Status:', payload.data.status);
break;
case ZapyEventTypes.QR_CODE:
// Handle QR code for authentication
console.log('QR Code:', payload.data.qr);
break;
case ZapyEventTypes.INSTANCE_STATUS:
// Handle instance status change
console.log('Instance:', payload.data.instanceId);
console.log('Status:', payload.data.status);
break;
case ZapyEventTypes.REACTION:
// Handle message reaction
console.log('Reaction:', payload.data.reaction);
console.log('Message ID:', payload.data.id);
break;
case ZapyEventTypes.PRESENCE:
// Handle presence update (typing, online, etc.)
console.log('Presence:', payload.data.presence);
console.log('Last seen:', payload.data.lastSeen);
break;
case ZapyEventTypes.CONTACT_CREATED:
case ZapyEventTypes.CONTACT_UPDATED:
// Handle contact events
console.log('Contact:', payload.data.contact.name);
break;
}
}
Signature Verification
Verify webhook signatures for security:
import { verifyWebhookSignature } from '@zapyapi/sdk';
app.post('/webhook', express.json(), (req, res) => {
const signature = req.headers['x-webhook-signature'];
const isValid = verifyWebhookSignature(
req.body,
signature,
process.env.WEBHOOK_SECRET
);
if (!isValid) {
return res.status(401).send('Invalid signature');
}
// Process webhook...
res.status(200).send('OK');
});
Error Handling
The SDK provides typed errors for better error handling:
import {
ZapyClient,
ZapyApiError,
AuthenticationError,
RateLimitError,
InstanceNotFoundError,
ValidationError
} from '@zapyapi/sdk';
try {
await client.messages.sendText('my-instance', {
to: '5511999999999',
message: 'Hello!'
});
} catch (error) {
if (error instanceof AuthenticationError) {
console.error('Invalid API key');
} else if (error instanceof RateLimitError) {
console.error('Rate limit exceeded, retry after:', error.retryAfter);
} else if (error instanceof InstanceNotFoundError) {
console.error('Instance not found');
} else if (error instanceof ValidationError) {
console.error('Invalid request:', error.message);
} else if (error instanceof ZapyApiError) {
console.error('API error:', error.statusCode, error.message);
}
}
Utilities
The SDK includes helpful utility functions:
import {
normalizePhone,
isValidPhone,
isGroup,
extractPhone
} from '@zapyapi/sdk';
// Normalize phone number to WhatsApp format
normalizePhone('11999999999'); // '5511999999999'
normalizePhone('+55 11 99999-9999'); // '5511999999999'
// Validate phone number
isValidPhone('5511999999999'); // true
isValidPhone('invalid'); // false
// Check if ID is a group
isGroup('5511999999999@s.whatsapp.net'); // false
isGroup('123456789@g.us'); // true
// Extract phone from WhatsApp ID
extractPhone('5511999999999@s.whatsapp.net'); // '5511999999999'
TypeScript Support
The SDK is written in TypeScript and provides full type definitions:
import type {
// Common types
ZapyClientOptions,
PaginationQuery,
PaginatedResponse,
// Instance types
Instance,
CreateInstanceOptions,
QRCodeResponse,
CheckNumberResult,
CheckNumbersResponse,
PresenceType,
SendPresenceOptions,
ProfilePictureResponse,
GroupParticipant,
GroupMetadata,
// Message types (for sending)
SendTextMessageOptions,
SendImageMessageOptions,
SendVideoMessageOptions,
SendAudioNoteMessageOptions,
SendDocumentMessageOptions,
SendLocationMessageOptions,
SendContactMessageOptions,
ContactCardInfo,
SendStickerMessageOptions,
SendReactionOptions,
MessageResponse,
// Message event types (received via webhooks)
ZapyMessage,
ZapyTextMessage,
ZapyImageMessage,
ZapyVideoMessage,
ZapyAudioMessage,
ZapyDocumentMessage,
ZapyStickerMessage,
ZapyLocationMessage,
ZapyContactMessage,
ZapyReactionMessage,
ZapyPollMessage,
ZapyCallMessage,
ZapyChatInfo,
ZapySenderInfo,
ZapyMessageStatus,
// Webhook payload types
ZapyWebhookPayload,
ZapyEventMap,
ZapyEventType,
ZapyQRCodeEvent,
ZapyInstanceStatusEvent,
ZapyPresenceEvent,
ZapyReactionEvent,
ZapyContactCreatedEvent,
ZapyContactUpdatedEvent,
ZapyContactDeduplicatedEvent,
ZapyContact
} from '@zapyapi/sdk';
ESM and CommonJS
The SDK supports both ESM and CommonJS:
// ESM
import { ZapyClient } from '@zapyapi/sdk';
// CommonJS
const { ZapyClient } = require('@zapyapi/sdk');