See for an explanation of "what is a Space?"
Depending on your business operations, our integration offers two unique approaches to consider:
There are a few requirements to consider before creating a Space, which are outlined below:
The Launch endpoint requires the id key to be populated. The id key uniquely identifies the Space and can be an identifier of your choosing, with a maximum length of 64 characters.
201 indicates that a new Space has been created. If a Space with the corresponding id already exists for your organisation, a status code of 200 will be returned and the details of the existing Space will be retrieved.
{
"id":"biology101-2023"
}
useruserclient_urlclient_urlSee more about the client_url paramter below and the user object .
{
"user":
{
"id":"Teacher_1",
"name":"Peter Parker",
"role": "teacher",
"leader":true, // Enabling Leader Mode
"custom_jwt_parameters":
{
"meta":
{
"displayName": "Spiderman"
}
}
}
}
The Lessonspace API provides the option to assign webhooks which can communicate real-time metrics such as user joins, session ends, etc. to your system.
The webhooks have to be set using the Launch endpoint.
You can set up your own webhooks by specifying them in the body of your POST request to the Launch endpoint. Any webhooks sent on any subsequent calls for the same Space (as identified by the id) will fully overwrite existing ones; they will not be merged in. This allows you to remove webhooks. You can leave webhooks as-is by simply not sending a new webhooks property.
{
"webhooks": {
"session": {
"start": "<endpoint-url>",
"end": "<endpoint-url>",
"idle": "<endpoint-url>"
},
"user": {
"join": "<endpoint-url>",
"leave": "<endpoint-url>",
"idle": "<endpoint-url>"
}
}
}
Given the above, an example of the body for a POST to the Launch endpoint can be seen below. This will create a Space with the following configuration (following the configuration as mentioned above):
client_url will be for the Teacher "Peter Parker" who will have enabled (leader set to true)ids could be some sort of relationship identifier for the people intended to join the Space, e.g. teacher123_student456. You could also use a term (as in our case) that identifies the lesson or course at hand, e.g. biology101_2023.
{
"id": "biology101_2023",
"user":
{
"id":"Teacher_1",
"name":"Peter Parker",
"role": "teacher",
"leader":true, // Enabling Leader Mode
"custom_jwt_parameters":
{
"meta":
{
"displayName": "Spiderman"
}
}
},
"webhooks":
{
"session":
{
"start": "<endpoint-url>",
"end": "<endpoint-url>",
"idle": "<endpoint-url>"
},
"user":
{
"join": "<endpoint-url>",
"leave": "<endpoint-url>",
"idle": "<endpoint-url>"
}
}
}
It is possible to have multiple potential leaders in a Space but we do not recommend this. Having multiple users leading at the same time will often lead to undesirable behaviour.
Below is a demo example using cURL, copy and paste it to give it a try - webhooks omitted:
{
"request": {
"method": "POST",
"url": "https://api.thelessonspace.com/v2/spaces/launch/",
"headers": [
{
"name": "Authorization",
"value": "Organisation __API_KEY__"
}
],
"postData": {
"mimeType": "application/json",
"text": "{\"id\": \"biology101_2023\", \"user\": {\"id\": \"Teacher_1\", \"name\": \"Peter Parker\", \"leader\": true, \"custom_jwt_parameters\": { \"meta\": { \"displayName\": \"Spiderman\" }}}}"
}
},
"response": {
"status": 200,
"httpVersion": "HTTP/2",
"headers": [
{
"name": "content-type",
"value": "application/json"
}
],
"content": {
"text": "{\"client_url\": \"https://go.room.sh/...\", \"api_base\": \"https://ew2-aa.room.sh/v1/room/\", \"room_id\": \"uuid\", \"secret\": \"uuid\", \"session_id\": \"uuid\",\"user_id\": \"int\"}",
"mimeType": "application/json"
}
}
}
Upon a successful Launch request, you will receive a JSON object similar to the following:
{
"client_url" : "https://go.room.sh/...",
"api_base" : "https://<region>.room.sh/v1/room/",
"room_id" : "uuid",
"secret" : "uuid",
"session_id" : "uuid",
"user_id" : "int"
}
Well done! Now open the client_url in your browser and you will be greeted by the lobby!
A little information about the returned object now follows (with a big focus on the client_url):
client_url refers to the raw URL of the Space itself (this url will contain go.room.sh). This URL has all of the settings specified by the user object (and other ) encoded as parameters. This allows you to create additional user specific client_urls for your Spaces depending on user requirements. See for more information.It is important to understand that the returned client_url uses all your default organisation settings if they are not set the in body of the POST request. This means that the URLs will contain the settings (state) of your organisation on creation and not when they are being used. If you create a link and change the organisation settings later these will not be applied to the old client_url; you will need to call the Launch Endpoint with the same Space ID again in order to apply the updated setttings.
api_base the endpoint used for all live sessions. This is region-specific and will automatically find the nearest server to you for low latency (unless explicitly overridden in the Launch parameters).room_id this UUID is used to identify your space within our backend (which manages sessions and whiteboard). It is the same identifier used for the Space in the Lessonspace API.secret token to ensure all calls to our backend are authenticated.session_id refers to the ID of the upcoming session. This ID will only change once a session has started and subsequently ended. Subsequent calls will then generate a new session_id.user_id is the unique identifier assinged to the user. This references the user record in Lessonspace database.client_url must be kept private and is only for use by the Tutor/Teacher assigned to the Space. See more about A user with leader mode enabled will be given certain privileges over and above all standard users (ie. those with leader mode set to false). These privileges include access to certain features and control over certain user actions.
Some examples include:

See above for an example.
If your server returns a status code outside the 200 - 299 range, or takes longer than 30 seconds (including connection and response time), the webhook delivery will be considered a failure and retries will begin.
The retry algorithm uses an exponential backoff, and will attempt to deliver a payload up to 5 times. In order to not count retry delay in statistics, you can use the x-webhook-time time header, described below.
Events are guaranteed to be delivered in-order on a per-space basis and per-URL basis with a single exception for the case of all retries failing. In that case, subsequent events will still be delivered.
Four custom headers are included with each delivery. These are:
x-webhook-id Uniquely identifies the webhook payload. Retries use the same value.x-webhook-event The type of event being dispatched.x-webhook-timestamp An ISO8601 timestamp specifying when the webhook event took place.x-webhook-signature A cryptographic signature for security and authentication.The x-webhook-signature header allows you to both authenticate that the request originates with Lessonspace (as only you and Lessonspace know the secret key) and also that the payload has not been modified. The signature is calculated as an HMAC (using the sha256 algorithm) of the webhook payload as stringified JSON (generated with JSON.stringify() in Node.js), using the space secret as the signing key.
If the payload is stringified using a similar operation in another language, such as json.dumps in Python, note that the semantics of JSON.stringify mean that all unimportant whitespace is automatically removed from the final string. For Python, an equivalent operation would be json.dumps(x, separators=(',', ':')).
It is not sufficient to simply copy-paste the payload and quote it to create a string.
webhooks.user.joinThis webhook is triggered when a user joins a Space. In other words, this happens when the user opens their web browser to the Space URL and joins the lobby.
webhooks.user.idleTriggered when a user is considered idle in a space. See Idle under Terms & Concepts for more information.
webhooks.user.leaveTriggered when a user leaves a space. It can be when they close their browser tab, click the End Session button, or are otherwise disconnected.
All the above webhooks have the same payload schema:
{
"session": {
"id": "internal identifier of the session"
},
"room": {
"id": "internal identifier of the space"
},
"socketId": "internal socket id of the user",
"user": {
"id": "identifier of the user",
"guest": "boolean flag indicating whether or not the user joined while signed in",
"readOnly": "boolean flag indicating whether or not the user was in read only mode",
"allowInvite": "boolean flag indicating whether or not the user had access to the Invite Others button",
"meta": ...,
"page": null,
"av": ...
},
"nbf": ...,
"exp": ...,
"canLead": "boolean flag indicating whether or not the user can lead",
"traceId": ...
}
webhooks.session.startTriggered when a space registers it's first user join. Payload schema:
{
"id": "internal identifier of the session",
"room": {
"id": "internal identifier of the space"
}
}
webhooks.session.idleTriggered when all the users in a space are considered idle. Payload schema:
{
"id": "internal identifier of the session",
"room": {
"id": "internal identifier of the space",
"allUsersIdle": true,
"becameIdleAt": "ISO860 date string indicating the datetime that the session became idle"
}
}
webhooks.session.endTriggered when a space registers it's last user leave, or timeouts have been reached. Payload schema:
{
"id": "internal identifier of the session",
"room": {
"id": "internal identifier of the space",
"allUsersIdle": "boolean indicating whether or not all users are idle",
"becameIdleAt": "ISO860 date string indicating the datetime that the session became idle"
},
"summary": {
"start": "ISO860 date string indicating start datetime of the session",
"end": "ISO860 date string indicating end datetime of the session"
},
"reason": {
"state": "ended",
"extra": "empty"
}
}
webhooks.chat.messageTriggered when a chat message is sent.
webhooks.cobrowser.startTriggered when a Cobrowser activity starts in a session.
webhooks.cobrowser.stopTriggered when a Cobrowser activity stops in a session.
webhooks.transcription.finishTriggered when a session finishes being transcribed.
{
"transcriptionUrl": "<pre-signed S3 URL>"
}