Skip to main content
Use vzaps.events to receive instance events in real time without exposing a public URL. For HTTP callbacks, see Webhooks.

Common events

EventDescription
MessageNew incoming message or message event.
ReadReceiptRead/delivery update.
PresenceUser presence.
ChatPresenceChat presence.
HistorySyncHistory synchronization.
ConnectedInstance connected to WhatsApp.
DisconnectedInstance disconnected.
GroupParticipantsAddParticipants added to group.
GroupParticipantsRemoveParticipants removed from group.
AllAll subscribed events.

Subscribe to realtime

const subscription = await vzaps.events.subscribe({
  instanceId: 'VZ...',
  instanceToken: 'instance-token',
  events: ['Message', 'ReadReceipt', 'Connected', 'Disconnected'],
  reconnect: true,
  maxRetries: 10,
  retryDelayMs: 1000,
});
Return: EventSubscription — object with on(), close(), and automatic reconnect when configured. Options:
FieldTypeRequiredDescription
instanceIdstringYesInstance to watch.
instanceTokenstringYesInstance token.
eventsVZapsEventType[]NoEvent list. If omitted, uses events subscribed on the instance.
reconnectbooleanNoReconnect automatically. Default: true.
maxRetriesnumberNoMaximum retry attempts.
retryDelayMsnumberNoDelay between retries.
lastEventIdstringNoResume cursor.
signalAbortSignalNoClose subscription when aborted.

Register handlers

subscription.on('open', () => {
  console.log('Realtime connected');
});

subscription.on('Message', (event) => {
  console.log(event.id);
  console.log(event.instance_id);
  console.dir(event.data, { depth: null });
});

subscription.on('All', (event) => {
  console.log('Received event:', event.type);
});

subscription.on('error', (error) => {
  console.error('Realtime error:', error);
});

Close subscription

await subscription.close();
Return: Promise<void> after the WebSocket closes. In Node.js processes:
process.on('SIGINT', async () => {
  await subscription.close();
  process.exit(0);
});

Event envelope

Every event received by the SDK has this shape:
{
  "id": "evt_01J...",
  "type": "Message",
  "instance_id": "VZ...",
  "created_at": "2026-06-23T22:57:17.000Z",
  "data": {
    "type": "Message",
    "media_url": "https://cdn.example.com/media/image.jpg"
  }
}
Fields:
FieldDescription
idEvent identifier. Use for deduplication.
typeEvent type.
instance_idSource instance.
created_atEvent creation date.
dataEvent payload.
data.media_urlMedia URL when the incoming event contains media and the platform provides the file.

Delivery and ack

Delivery is at-least-once. Your app should process events idempotently. After the handler finishes, the SDK automatically sends an ack. Recommendations:
  • store event.id if your automation performs external effects;
  • ignore events that were already processed;
  • use lastEventId when reconnecting if you want to reduce gaps;
  • keep handlers fast and move long-running work to your own queue.

Realtime or webhook?

ScenarioRecommendation
Bot, dashboard, or app with immediate consumptionRealtime
Backend with public URL and HTTP pipelineWebhook
Do not want to expose a public URLRealtime
Need to reprocess deliveries via logsWebhook