Customer chats
Let members and staff start conversations on any subject, outside of a reservation.
A customer chat is a conversation between one person of the club (a member or an applicant) and the club team about a subject of their choice. Either side can start it, and a person can keep several chats open at once. Reservation conversations stay attached to their reservation (see Reservations).
Staff need the customer_chats permission in the club; club administrators always have it.
Members can only reach their own chats in the club of their session.
Staff inbox
query CustomerChats($clubId: ID!, $archived: Boolean!) {
customerChats(clubId: $clubId, archived: $archived) {
id
personId
personName
subject
createdAt
archivedAt
unread
lastMessage {
author
senderName
body
createdAt
}
}
}| Argument | Type | Description |
|---|---|---|
clubId | ID! | Club whose chats are listed. |
archived | Boolean! | false (default) lists active chats, true the archived ones. |
Every staff member with access sees every chat of the club, sorted by latest message first.
unread and archivedAt belong to the caller: a chat is unread while a customer message is newer
than the caller's last read, and archiving it never affects another staff member. Any new message,
from either side, restores the chat to every staff member's active list.
query CustomerChat($clubId: ID!, $chatId: ID!) {
customerChat(clubId: $clubId, chatId: $chatId) {
id
personId
personName
subject
messages {
id
author
senderName
body
createdAt
}
}
}
mutation ReadCustomerChat($clubId: ID!, $chatId: ID!) {
markCustomerChatRead(clubId: $clubId, chatId: $chatId)
}
mutation ArchiveCustomerChat($clubId: ID!, $chatId: ID!) {
setCustomerChatArchived(clubId: $clubId, chatId: $chatId, archived: true)
}customerChat returns null for a chat of another club. Messages are ordered oldest first;
author is customer or professional. markCustomerChatRead and setCustomerChatArchived
return false when the chat does not exist in the club.
Start and answer as staff
mutation StartCustomerChat($clubId: ID!, $personId: ID!, $subject: String!, $body: String!) {
startCustomerChat(clubId: $clubId, personId: $personId, subject: $subject, body: $body) {
id
subject
}
}
mutation PostCustomerChatMessage($clubId: ID!, $chatId: ID!, $body: String!) {
postCustomerChatMessage(clubId: $clubId, chatId: $chatId, body: $body) {
id
messages {
id
body
}
}
}The person must belong to clubId. Messages are signed with the staff member's name, or
Club team when it is empty, and are immediately read for the sender. Each staff message sends
the member a chat notification in the app and by email (according to their preferences)
linking to /account/chats/{chatId}, and emits the chat.message webhook. Starting a chat is
recorded as customer_chat.started and later replies as customer_chat.message_posted in the
staff activity log.
Member operations
query MyCustomerChats($clubId: ID!) {
myCustomerChats(clubId: $clubId) {
id
subject
unread
lastMessage {
author
senderName
body
createdAt
}
}
}
mutation StartMyCustomerChat($clubId: ID!, $subject: String!, $body: String!) {
startMyCustomerChat(clubId: $clubId, subject: $subject, body: $body) {
id
}
}myCustomerChat(clubId, chatId), postMyCustomerChatMessage(clubId, chatId, body) and
markMyCustomerChatRead(clubId, chatId) complete the member API. A member chat is unread while
a professional message is newer than the member's last read; the member's own messages count as
read. Chats of another member return null (or false for markMyCustomerChatRead). Members of
another club and staff accounts receive UNAUTHENTICATED. Customer messages are signed with the
member's name and do not notify staff beyond the unread state of their inbox.
Validation
Subjects are trimmed and must contain 1 to 120 characters; message bodies are trimmed and must
contain 1 to 4000 characters. Invalid IDs and out-of-range values return BAD_USER_INPUT.