Skip to content

PulseClient API

When Do You Need This?

Most users only need <pulse-widget>. The PulseClient API is for building your own custom UI instead of using the built-in widget.

PulseClient is the low-level client that connects to the Pulse server. The widget uses it internally.

Setup

typescript
import { PulseClient } from '@gamention/pulse-core';

const client = new PulseClient({
  apiKey: 'pk_your_key',
  token: userToken,
  room: 'dashboard',
  endpoint: 'wss://pulse.hire.rest'
});

client.connect();
OptionTypeRequiredDescription
apiKeystringYesPublishable key (pk_...)
tokenstringYesUser JWT from /auth/token
roomstringYesRoom identifier
endpointstringYesPulse server WebSocket URL

Connection

typescript
client.connect();                           // Connect
client.disconnect();                        // Disconnect and clean up
console.log(client.connectionState);        // "connected" | "connecting" | "disconnected"

client.on('connection', (state) => { ... });  // Listen for changes

Reconnection

Pulse automatically reconnects with exponential backoff:

  • Base delay: 1 second
  • Maximum delay: 30 seconds
  • Presence heartbeat: every 30 seconds
  • Users appear offline after: 60 seconds of no heartbeat

On reconnect, the client re-authenticates and receives the full current state from the server. You do not need to handle reconnection manually.

Threads & Comments

typescript
// Create a thread (returns the thread ID)
const threadId = client.createThread('This button looks off', {
  mentions: ['user-2'],                  // optional @mentions
  position: { x: 0.45, y: 0.72 },       // optional pin position (0-1 range)
  attachmentIds: ['attach-uuid'],        // optional pre-uploaded attachment IDs
});

// Reply to a thread (returns the comment ID)
// Fourth argument is an optional array of attachment IDs
const commentId = client.reply('thread-id', 'Agreed, fixing now', ['user-1'], ['attach-uuid']);

// Edit your own comment
client.editComment('comment-id', 'Updated text', []);

// Delete your own comment — applies optimistic local removal immediately
client.deleteComment('comment-id');

// Resolve / reopen a thread
client.resolveThread('thread-id', true);   // resolve
client.resolveThread('thread-id', false);  // reopen

Reactions

typescript
client.addReaction('comment-id', 'comment', '👍');
client.removeReaction('reaction-id');

Presence & Cursors

typescript
client.moveCursor({ x: 0.5, y: 0.3, pageX: 500, pageY: 300 });
client.updatePresence('idle');           // 'online' | 'idle'
client.setAppearOffline(true);           // hide from presence

Other Interactions

typescript
client.sendTyping('thread-id');          // typing indicator
client.performClick({ x: 0.5, y: 0.3, pageX: 500, pageY: 300 });

// Send an emoji drop visible to all users in the room
client.dropEmoji('🎉', { x: 0.5, y: 0.3, pageX: 500, pageY: 300 });

client.drawStroke(
  [{ x: 100, y: 200 }, { x: 150, y: 250 }],
  '#ff0000', 3
);
client.clearDrawing();

Notifications

typescript
client.markRead('notification-id');

// Mark all as read — optimistic local update, no server round-trip wait
client.markAllRead();

File Uploads

typescript
// Upload a file — returns attachment metadata
const attachment = await client.uploadFile(file);
// { id, type, filename, url, thumbnailUrl? }

// Then pass the ID when creating a thread or reply
client.createThread('See attached', { attachmentIds: [attachment.id] });

Uploads go to POST /api/v1/upload using the same pk_ + JWT credentials as the WebSocket connection. Errors (file too large, type disabled) are thrown as Error with the server's message.

See Upload API for the full endpoint reference.

Accessing State

typescript
client.state.user;           // Current user (PulseUser)
client.state.threads;        // All threads (Thread[])
client.state.presence;       // Online users (PresenceUser[])
client.state.notifications;  // User notifications (Notification[])
client.state.reactions;       // All reactions (Reaction[])
client.state.users;          // All known users in the room (PulseUser[])
client.state.config;         // Environment feature flags (EnvironmentConfig)
client.state.getUser('id');  // Look up any user by ID

See State & Events for subscribing to changes.

Pulse Collaboration SDK