Skip to content

Signals

Signals are live events the Hailer host pushes into your app — an activity was created, a ball was passed, the workspace changed. You receive them through the signals callback you pass to HailerApi.

ts
const hailer = new HailerApi({
  signals: signal => {
    if (signal.name === 'activity.update') {
      refreshActivity(signal.data.activityIds);
    }
  },
});

Each signal is a Signal object: { name: string; data: any }.

The signal whitelist

The host only forwards a fixed, renamed set of internal events — you can't subscribe to arbitrary events. These are the names your signals callback can receive:

Signal nameFires whendata
activity.createAn activity is created{ activityIds, workflowId, phaseId }
activity.updateAn activity is updated{ activityIds, workflowId, phaseId }
activity.removeAn activity is removed{ activityIds, workflowId, phaseId }
activity.ball.passedA ball is passedBall event payload
activity.ball.takenA ball is takenBall event payload
activity.ball.clearedA ball is clearedBall event payload
activity.ball.autoAssignedA ball is auto-assignedBall event payload
insight.createAn insight is createdInsight payload
insight.updateAn insight is updatedInsight payload
insight.removeAn insight is removedInsight payload
workspace.invitation.newThe user receives a workspace invitationInvitation payload
workspace.invitation.removeA workspace invitation is removedInvitation payload
workspace.role.createA workspace role is createdRole payload
workspace.role.updateA workspace role is updatedRole payload
workspace.role.removeA workspace role is removedRole payload
workspace.currentThe user switches the active workspace{ workspaceId }

Names are translated at the boundary

These SDK names differ from Hailer's internal event names — the host renames each event before forwarding it. Match on the SDK name in the table above, not on any internal name you may see elsewhere.

Not every internal event is available

Some events (e.g. workspace reload and feed posts) are deliberately not forwarded — there is no way to subscribe to them from an app. If a change you need isn't in the table above, poll the relevant module instead.

Activity signals carry ids, not activities

activity.create / update / remove give you activityIds, workflowId, and phaseId — not the full activity. Load what you need in response:

ts
signals: async signal => {
  if (signal.name === 'activity.update') {
    const { activityIds } = signal.data;
    const ids = Array.isArray(activityIds) ? activityIds : [activityIds];
    for (const id of ids) {
      const activity = await hailer.activity.get(id);
      // update your view
    }
  }
},

An update to an activity that was removed arrives as activity.remove (not activity.update), so branch on signal.name.

React to workspace switches

workspace.current fires whenever the user changes their active workspace in Hailer. In a private app this is your cue to re-scope what you show:

ts
signals: signal => {
  if (signal.name === 'workspace.current') {
    reloadForWorkspace(signal.data.workspaceId);
  }
},

Next steps

Hailer Developer Documentation