Use TalkJS webhooks to be notified about events that happen in your application between your users.

Webhook events

TalkJS supports following webhook calls:

  • user.created: Occurs when a user is created in TalkJS backend.
  • user.updated: Occurs when a user is updated in TalkJS backend.
  • message.sent: Occurs when a message is sent in a conversation.
  • message.read: Occurs when another user in the same conversation receives the message in the chat UI. This event will get sent at most once for every member of a conversation other than the sender.
  • notification.triggered: Occurs when TalkJS decided that a notification is to be sent to a user. In particular, this is the case when both of the following conditions are met:
    1. One or more messages have been sent by one or more users and the user(s) stopped typing or went offline, indicating that no further messages are to be expected
    2. Another user was not currently online and looking at the same conversation, indicating that they might have missed the messages sent and thus should be notified.
  • notification.sent: Occurs when TalkJS has actually sent the aforementioned notification. May be triggered more than once for each notification if TalkJS notifies a user both via email and SMS. Does not get triggered for mobile push notifications.
  • notification.delivered - Occurs when a email was successfully delivered.
  • notification.bounced - Occurs when an email was not successfully delivered. It is triggered for bounces and spam complaints that resulted from outgoing email.
  • notification.opened - Occurs when a user opens an email notification in an email client. Note that it may not always be triggered, because user’s email client might be blocking tracking pixels.
  • notification.link.clicked - Occurs when a user clicks a link inside an email notification.

Note that the notification.triggered event will occur even if a user has no email or phone number set. This allows you to substitute TalkJS's notification features by your own, if you wish.

You can see examples on how to use TalkJS Webhooks in our examples repository on GitHub.

We are working hard on adding more events, get in touch with us if you have any suggestions!

Events

Webhook data is sent as JSON in the POST request body. In order to acknowledge the reception of an event your endpoint should return a 200 HTTP status code. If a webhook is not successfully received for any reason, TalkJS will retry 10 times with an exponential backoff. You can set up your webhook URL in the dashboard.

All events have the same top-level structure, as shown below. Only the structure of the data field differs for every type:

type Event = {
  id: string;
  createdAt: number; // UNIX timestamp in milliseconds
  data: any;
  type: string;
};

Event structure

The supported webhook events are structured as follows:

type UserCreatedEvent = {
  id: string;
  createdAt: UnixMilliseconds;  
  data: {
    user: User;
  }
  type: "user.created";
}
type UserUpdatedEvent = {
  id: string;
  createdAt: UnixMilliseconds;  
  data: {
    user: User;
  }
  type: "user.updated";
}
type MessageSentEvent = {
  id: string;
  createdAt: UnixMilliseconds;
  data: {
    sender: User;
    conversation: Conversation;
    message: Message;
  }
  type: "message.sent";
};
type MessageReadEvent = {
  id: string;
  createdAt: UnixMilliseconds;
  data: {
    recipient: User;
    conversation: Conversation;
    message: Message;
  };
  type: "message.read";
};
type NotificationTriggered = {
  id: string;
  createdAt: UnixMilliseconds;
  data: {
    notificationId: string;
    recipient: User;
    sender: User;
    conversation: Conversation;
    messages: Message[];
  };
  type: "notification.triggered";
};
type NotificationSent = {
  id: string;
  createdAt: UnixMilliseconds;  
  data: {
    notificationId: string;
    recipient: User;
    sender: User;
    conversation: Conversation;
    messages: Message[];
    channel: "email" | "sms";
  };
  type: "notification.sent";
};
type NotificationDelivered = {
  id: string;
  createdAt: UnixMilliseconds;  
  data: {
    notificationId: NotificationId;
    conversation: Conversation;
    messages: Message[];
    recipient: User;
    sender: User;
    channel: "email";
  };
  type: "notification.delivered";
}
type NotificationBounced = {
  id: string;
  createdAt: UnixMilliseconds;  
  data: {
    notificationId: NotificationId;
    conversation: Conversation;
    messages: Message[];
    recipient: User;
    sender: User;
    channel: "email";
  };
  type: "notification.bounced";
}
type NotificationOpened = {
  id: string;
  createdAt: UnixMilliseconds;  
  data: {
    notificationId: NotificationId;
    conversation: Conversation;
    messages: Message[];
    recipient: User;
    sender: User;
    channel: "email"
  };
  type: "notification.opened";
}
type NotificationLinkClicked = {
  id: string;
  createdAt: UnixMilliseconds;  
  data: {
    notificationId: NotificationId;
    conversation: Conversation;
    messages: Message[];
    recipient: User;
    sender: User;
    channel: "email";
    originalUrl: string;
  };
  type: "notification.link.clicked";
}

The interfaces of the types presented above are the following:

type UserId = string;
type ConversationId = string;
type MessageId = string;
type UnixMilliseconds = number;
type ByteSize = number;

type Message = {
  id: MessageId;
  conversationId: ConversationId;
  type: "UserMessage" | "SystemMessage";
  readBy: UserId[];
  senderId: UserId;
  text?: string;
  attachment?: File;
  origin: "web" | "rest" | "email" | "import";
  location?: Coordinates;
  createdAt: UnixMilliseconds;
};
type Conversation = {
  id: ConversationId;
  subject?: string;
  topicId?: string;
  photoUrl?: string;
  custom?: {[name: string]: string };
  participants: {
    [id: UserId]: {access: "ReadWrite" | "Read", notify: boolean}
  };
  createdAt: UnixMilliseconds;
}
type User = {
  id: UserId;
  name: string;
  welcomeMessage?: string;
  photoUrl?: string;
  headerPhotoUrl?: string;
  configuration?: string;
  email?: string[] | null;
  phone?: string[] | null;
  custom?: {[name: string]: string };
  availabilityText?: string;
  locale?: string;
  createdAt: UnixMilliseconds;
};
type File = {
  url: string;
  size: ByteSize;
}
type Coordinates = [
  number, // latitude
  number  // longitude
]