This document describes current Clinked WebSocket. It is a raw WebSocket with STOMP subprotocol.

1. Connecting

A STOMP client can connect to a broker at wss://api.clinked.com/websocket.

The endpoint is protected, which means Authorization header with API access token is required for authentication. See API documentation page for more details on how to obtain it.

2. Topics

Clinked provides a several topics a client can subscribe to. Each message has clinked-type header that can be used to determine message type and how to parse a message body.

2.1. User notifications

User global notifications. This topic notifies about user related activity e.g. new notifications, unread notification count change, event invitations, etc.

Topic: /user/queue/notifications

2.1.1. Chat activity notification

Gets emitted when someone sends a message to a conversation a subscribed user participates in.

Message example
MESSAGE
clinked-type:chat-activity
destination:/user/queue/notifications
content-type:application/json;charset=UTF-8
subscription:-592277089
message-id:1-19
content-length:51

{"conversation":"b92a1ff59c170349b9277a06433c4c46","organisation":"3","message":"Hello","messageSource":"Richard Atkins"}

2.1.2. User request created

A request can be an invitation to attend in a calendar event.

Message example
MESSAGE
clinked-type:request
destination:/user/queue/notifications
content-type:application/json;charset=UTF-8
subscription:-592277089
message-id:1-27
content-length:3149

{"id":25,"contextKey":{"id":85,"parent":{"id":13,"parent":{"id":12,"parent":null,"objectType":"com.rabbitsoft.clinked.domain.Organisation","objectId":3},"objectType":"com.rabbitsoft.clinked.domain.Space","objectId":1},"objectType":"com.rabbitsoft.clinked.domain.Event","objectId":4},"organisation":{"id":3,"comments":0,"attachments":0,"contextKey":{"id":12,"parent":null,"objectType":"com.rabbitsoft.clinked.domain.Organisation","objectId":3},"creator":{"id":9,"comments":0,"attachments":0,"contextKey":{"id":11,"parent":null,"objectType":"com.rabbitsoft.clinked.domain.User","objectId":9},"username":"andrejs","enabled":true,"locked":false,"twoFactorAuthentication":false,"lastModified":1555317091000,"lastLogin":1555317091000,"dateCreated":1551874962000,"dateActivated":1551875515000,"name":"andrejs","jobTitle":null,"organisation":null,"email":"andrejs.mivreniks@clinked.com","address":null,"telephone":"2","other":null,"logo":false,"timeZone":"Europe/Helsinki","locale":"en_GB","verifiedEmail":true,"twoFactorMode":null,"timeZoneOffset":180,"type":"user"},"name":"myorg","friendlyName":"myorg","dateCreated":1551874962000,"lastModified":1554382343000,"enabled":true,"domain":null,"mobileSchema":null,"branding":{"backgroundColor":"#f8f8f8","textColor":"#777777","logo":false,"logoLarge":false,"logoMedium":false,"background":false,"favicon":false,"textLogo":false,"gradient":false,"gradientWidth":400},"samlConfiguration":{"entityId":null,"ssoEnabled":false,"userJit":true,"forceSso":false,"adminsUsePassword":true,"disableProfileEdit":false},"hash":"8f9d78e3-d325-42c0-8511-510a37548878","type":"account"},"source":{"id":11,"comments":null,"attachments":null,"contextKey":{"id":84,"parent":null,"objectType":"com.rabbitsoft.clinked.domain.User","objectId":11},"username":"andrejs2","enabled":true,"locked":false,"twoFactorAuthentication":false,"lastModified":1555317683579,"lastLogin":1555317683578,"dateCreated":1554382397000,"dateActivated":1554382397000,"name":"andrejs2","jobTitle":null,"organisation":null,"email":"andrejs.mivreniks@clinked.com","address":null,"telephone":null,"other":null,"logo":false,"timeZone":"Europe/Helsinki","locale":"en_GB","verifiedEmail":true,"twoFactorMode":null,"timeZoneOffset":180,"type":"user"},"target":{"id":9,"comments":0,"attachments":0,"contextKey":{"id":11,"parent":null,"objectType":"com.rabbitsoft.clinked.domain.User","objectId":9},"username":"andrejs","enabled":true,"locked":false,"twoFactorAuthentication":false,"lastModified":1555317091000,"lastLogin":1555317091000,"dateCreated":1551874962000,"dateActivated":1551875515000,"name":"andrejs","jobTitle":null,"organisation":null,"email":"andrejs.mivreniks@clinked.com","address":null,"telephone":"2","other":null,"logo":false,"timeZone":"Europe/Helsinki","locale":"en_GB","verifiedEmail":true,"twoFactorMode":null,"timeZoneOffset":180,"type":"user"},"sourceName":"andrejs.mivreniks@clinked.com","targetName":"andrejs.mivreniks@clinked.com","type":"ACCEPT_DECLINE_MAYBE","status":"NONE","scope":null,"parameters":null,"lastModified":1555317935968,"inviteKey":null,"requestName":"requests.event","requestTypeName":"requests.accept_decline_maybe","originalTargetName":"andrejs.mivreniks@clinked.com"}

2.1.3. Notification received

User notification.

MESSAGE
clinked-type:notification
destination:/user/queue/notifications
content-type:application/json;charset=UTF-8
subscription:-592277089
message-id:1-21
content-length:338

{"id":20,"source":{"name":"andrejs2","uri":"uri:user:andrejs2"},"target":{"name":"andrejs","uri":"uri:user:andrejs"},"type":"MENTION_COMMENT","message":"@andrejs What do you think about this? ","containerUri":null,"uri":"uri:ctx:28","displayName":"Help Videos","read":false,"immediate":false,"delivered":false,"dateCreated":1555317713490}

2.1.4. Notification unread count update

Notifies a client about unread notification count update.

MESSAGE
clinked-type:count
destination:/user/queue/notifications
content-type:application/json;charset=UTF-8
subscription:-592277089
message-id:1-22
content-length:12

{"count":20}

2.1.5. Group membership update

Notifies a client about group membership updates to instantly update any group lists visible to a user.

Group added

This message is sent when an authenticated user gets added to a group or a group is restored from trash.

MESSAGE
clinked-type:group-add(1)
clinked-account:myorg(2)
destination:/user/queue/notifications
content-type:application/json;charset=UTF-8
subscription:sub-0
message-id:a-21
content-length:45

{"name":"mygroup","id":14,"friendlyName":"My Group"}
1 Message type
2 Account name
Group removed

This message is sent when an authenticated user gets removed from a group or a group is removed.

MESSAGE
clinked-type:group-remove(1)
clinked-account:myorg(2)
destination:/user/queue/notifications
content-type:application/json;charset=UTF-8
subscription:sub-0
message-id:a-21
content-length:45

{"name":"mygroup","id":14,"friendlyName":"My Group"}
1 Message type
2 Account name

2.1.6. User online status update

Notifies a client about user online status updates.

MESSAGE
clinked-type:online-user
destination:/user/queue/notifications
content-type:application/json;charset=UTF-8
subscription:1378c63b-ceda-43b7-bb06-4b8565f53379
message-id:7-35
content-length:60

{"uri:user:andrejs:11":true,"uri:user:roger.smith:14":false}

2.2. User group activity

Activity notifications from groups a user is part of.

Topic: /user/queue/activity

MESSAGE
clinked-type:update
destination:/user/queue/activity
content-type:application/json;charset=UTF-8
subscription:-122846445
message-id:1-20
content-length:4637

{"id":"402881e76a201ebe016a2028e62a0003","messageCode":"update.comment.create","message":"<a href=\"http://myorg.localhost.localdomain:8080/people/andrejs\">@andrejs</a> What do you think about this? <br />","lastModified":1555317712383,"organisationId":3,"spaceId":1,"componentId":28,"componentEntityId":1,"userId":11,"targetUserId":null,"componentName":"Help Videos","reservedName":"mentions:andrejs","userName":"andrejs2","targetUserName":null,"users":[9,11],"trackingUsers":[2,9],"attachments":[],"published":false,"commentCount":0,"component":null,"user":null,"targetUser":null,"type":"update","accountName":"myorg","groupName":"Explore Clinked","account":{"id":3,"comments":0,"attachments":0,"contextKey":{"id":12,"parent":null,"objectType":"com.rabbitsoft.clinked.domain.Organisation","objectId":3},"creator":{"id":9,"comments":0,"attachments":0,"contextKey":{"id":11,"parent":null,"objectType":"com.rabbitsoft.clinked.domain.User","objectId":9},"username":"andrejs","enabled":true,"locked":false,"twoFactorAuthentication":false,"lastModified":1555317091000,"lastLogin":1555317091000,"dateCreated":1551874962000,"dateActivated":1551875515000,"name":"andrejs","jobTitle":null,"organisation":null,"email":"andrejs.mivreniks@clinked.com","address":null,"telephone":"2","other":null,"logo":false,"timeZone":"Europe/Helsinki","locale":"en_GB","verifiedEmail":true,"twoFactorMode":null,"timeZoneOffset":180,"type":"user"},"name":"myorg","friendlyName":"myorg","dateCreated":1551874962000,"lastModified":1554382343000,"enabled":true,"domain":null,"mobileSchema":null,"branding":{"backgroundColor":"#f8f8f8","textColor":"#777777","logo":false,"logoLarge":false,"logoMedium":false,"background":false,"favicon":false,"textLogo":false,"gradient":false,"gradientWidth":400},"samlConfiguration":{"entityId":null,"ssoEnabled":false,"userJit":true,"forceSso":false,"adminsUsePassword":true,"disableProfileEdit":false},"hash":"8f9d78e3-d325-42c0-8511-510a37548878","type":"account"},"group":{"id":1,"comments":0,"attachments":0,"contextKey":{"id":13,"parent":{"id":12,"parent":null,"objectType":"com.rabbitsoft.clinked.domain.Organisation","objectId":3},"objectType":"com.rabbitsoft.clinked.domain.Space","objectId":1},"owner":{"id":9,"comments":0,"attachments":0,"contextKey":{"id":11,"parent":null,"objectType":"com.rabbitsoft.clinked.domain.User","objectId":9},"username":"andrejs","enabled":true,"locked":false,"twoFactorAuthentication":false,"lastModified":1555317091000,"lastLogin":1555317091000,"dateCreated":1551874962000,"dateActivated":1551875515000,"name":"andrejs","jobTitle":null,"organisation":null,"email":"andrejs.mivreniks@clinked.com","address":null,"telephone":"2","other":null,"logo":false,"timeZone":"Europe/Helsinki","locale":"en_GB","verifiedEmail":true,"twoFactorMode":null,"timeZoneOffset":180,"type":"user"},"name":"explore_3","friendlyName":"Explore Clinked","members":7,"branding":{"headerColor":"#000000","textColor":"#ffffff","logo":true,"alignment":"left"},"published":false,"defaultPublic":false,"storageConsumed":3403049,"dateCreated":1551874968000,"lastModified":1551874968000,"mailKey":"40rgtP","order":1000,"hash":"5cd28a4b-870f-4f8d-80f1-bd4c9f448add","blind":false,"disableChat":false,"disableWidgets":false,"disableComments":false,"disableAccordionWidgets":true,"duplicate":false,"type":"group","public":false,"account":{"id":3,"comments":0,"attachments":0,"contextKey":{"id":12,"parent":null,"objectType":"com.rabbitsoft.clinked.domain.Organisation","objectId":3},"creator":{"id":9,"comments":0,"attachments":0,"contextKey":{"id":11,"parent":null,"objectType":"com.rabbitsoft.clinked.domain.User","objectId":9},"username":"andrejs","enabled":true,"locked":false,"twoFactorAuthentication":false,"lastModified":1555317091000,"lastLogin":1555317091000,"dateCreated":1551874962000,"dateActivated":1551875515000,"name":"andrejs","jobTitle":null,"organisation":null,"email":"andrejs.mivreniks@clinked.com","address":null,"telephone":"2","other":null,"logo":false,"timeZone":"Europe/Helsinki","locale":"en_GB","verifiedEmail":true,"twoFactorMode":null,"timeZoneOffset":180,"type":"user"},"name":"myorg","friendlyName":"myorg","dateCreated":1551874962000,"lastModified":1554382343000,"enabled":true,"domain":null,"mobileSchema":null,"branding":{"backgroundColor":"#f8f8f8","textColor":"#777777","logo":false,"logoLarge":false,"logoMedium":false,"background":false,"favicon":false,"textLogo":false,"gradient":false,"gradientWidth":400},"samlConfiguration":{"entityId":null,"ssoEnabled":false,"userJit":true,"forceSso":false,"adminsUsePassword":true,"disableProfileEdit":false},"hash":"8f9d78e3-d325-42c0-8511-510a37548878","type":"account"}}}

2.3. Chat

Any message to the server will reset chat online expiration timer. If no data needs to be sent, a client should send a heart beat frame ("\n") every 30 seconds to keep user online.

Topic: /topic/chat/{conversationId}

2.3.1. Online participants update

Emits updated list of online participants when someone joins or leaves a chat.

MESSAGE
clinked-type:chat-online
destination:/topic/chat/3ce8121bdff17563de7d564f7c63c1e6
content-type:application/json;charset=UTF-8
subscription:-55577369
message-id:2-29
content-length:1209

[{"id":11,"comments":null,"attachments":null,"contextKey":{"id":84,"parent":null,"objectType":"com.rabbitsoft.clinked.domain.User","objectId":11},"username":"andrejs2","enabled":true,"locked":false,"twoFactorAuthentication":false,"lastModified":1555317683000,"lastLogin":1555317683000,"dateCreated":1554382397000,"dateActivated":1554382397000,"name":"andrejs2","jobTitle":null,"organisation":null,"email":"andrejs.mivreniks@clinked.com","address":null,"telephone":null,"other":null,"logo":false,"timeZone":"Europe/Helsinki","locale":"en_GB","verifiedEmail":true,"twoFactorMode":null,"timeZoneOffset":180,"type":"user"},{"id":9,"comments":0,"attachments":0,"contextKey":{"id":11,"parent":null,"objectType":"com.rabbitsoft.clinked.domain.User","objectId":9},"username":"andrejs","enabled":true,"locked":false,"twoFactorAuthentication":false,"lastModified":1555317091000,"lastLogin":1555317091000,"dateCreated":1551874962000,"dateActivated":1551875515000,"name":"andrejs","jobTitle":null,"organisation":null,"email":"andrejs.mivreniks@clinked.com","address":null,"telephone":"2","other":null,"logo":false,"timeZone":"Europe/Helsinki","locale":"en_GB","verifiedEmail":true,"twoFactorMode":null,"timeZoneOffset":180,"type":"user"}]

2.3.2. Typing status change

When someone starts or stops typing a message in chat.

MESSAGE
clinked-type:chat-message
destination:/topic/chat/3ce8121bdff17563de7d564f7c63c1e6
content-type:application/json;charset=UTF-8
subscription:-55577369
message-id:2-30
content-length:299

{"properties":["nothumb"],"id":null,"deliveryId":"3ce8121bdff17563de7d564f7c63c1e6s0okpdx69m","conversation":"3ce8121bdff17563de7d564f7c63c1e6","source":{"properties":[],"id":"uri:user:andrejs:9","name":"andrejs"},"body":"yes","type":"type","dateReceived":"2019-04-15T08:47:04.762+0000","read":true}

2.3.3. Chat message

When someone creates a message in chat.

MESSAGE
clinked-type:chat-message
destination:/topic/chat/3ce8121bdff17563de7d564f7c63c1e6
content-type:application/json;charset=UTF-8
subscription:-55577369
message-id:2-32
content-length:330

{"properties":["nothumb"],"id":"093405b5cc5ac94e8865e893b156dc80","deliveryId":"3ce8121bdff17563de7d564f7c63c1e6ghz2ryap4gt","conversation":"3ce8121bdff17563de7d564f7c63c1e6","source":{"properties":[],"id":"uri:user:andrejs:9","name":"andrejs"},"body":"fff","type":"text","dateReceived":"2019-04-15T08:47:07.359+0000","read":true}

3. Operations

Additional operations supported by broker.

3.1. Create conversation message

Publish a message to /chat/{conversationId} with JSON serialized message object.

Chat message
{
    "conversation": "443443B0-CF76-4D0C-AA92-B965AA4C189B", (1)
    "deliveryId": "C0D54D5D-5A83-42B2-9466-6339808632B9", (2)
    "body": "Hello, World!", (3)
    "type": "text",
    "properties": []
}
1 Conversation (chat) id
2 Delivery id generated by a client
3 Chat message text
Typing status change
{
    "conversation": "443443B0-CF76-4D0C-AA92-B965AA4C189B",
    "deliveryId": "EFB70927-43AA-40B7-907D-19A1E3A252D0",
    "body": "yes", (1)
    "type": "type",
    "properties": []
}
1 Set to yes when typing, otherwise no

3.2. Get unread conversations

Publishing to /chat.unread will send a list of unread user conversations to the topic /user/queue/chat.unread.

3.3. Mark a conversation as read

You can publish to /chat/{conversationId}/read to mark a conversation as read. The server will send a fresh list of unread conversations to /user/queue/chat.unread.

3.4. Error callback

A client can subscribe to the topic /user/queue/errors to get notified about errors. Might be useful for debugging purposes.