Lessonspace

Webhooks

The Lessonspace API provides various webhooks you can use to get information about Spaces in real-time. The webhooks URL have to be set using the Launch endpoint when a Space is first created. Once set, the endpoint-url used cannot be changed later on.

Setting up Webhooks

You can set up your own webhooks by specifying them in the body of your POST request to the Launch endpoint when first creating the Space. Any webhooks provided on subsequent calls will be ignored. The webhooks are defined as follows:

{
  "webhooks": {
    "session": {
      "start": "<endpoint-url>",
      "end": "<endpoint-url>",
      "idle": "<endpoint-url>"
    },
    "user": {
      "join": "<endpoint-url>",
      "leave": "<endpoint-url>",
      "idle": "<endpoint-url>"
    }
  }
}

Retries & Ordering

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, per URL basis - with a single exception for where all retries have failed. In that case, subsequent events will still be delivered.

Headers

Three 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.

Security

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 of the webhook payload, using the space secret as the key. The space secret is exposed in the response when making a request to the Launch API.

Events

All the webhooks.user webhooks have the same payload schema which is given below.

{
  "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.user.join

This webhook is triggered when a user joins a Space. In other words, this happens when the user opens their web browser to the URL and joins the lobby.

webhooks.user.idle

Triggered when a user is considered idle in a space. See Idle under Terms & Concepts

webhooks.user.leave

Triggered when a user leaves a space. It can be when they close their browser tab, clicks the End Session button, or is otherwise disconnected.

webhooks.session.start

Triggered when a space has its first user join.

Payload Schema

{
  "id": "internal identifier of the session",
  "room": {
    "id": "internal identifier of the space"
  }
}

webhooks.session.idle

Triggered 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.end

Triggered when a space has its 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

See Adding Webhooks above for an example.

Retries & Ordering

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.

Headers

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.

Security

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.

The space secret is exposed in the response when making a request to the Launch API.

Events

webhooks.user.join

This 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.idle

Triggered when a user is considered idle in a space. See Idle under Terms & Concepts for more information.

webhooks.user.leave

Triggered 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.start

Triggered 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.idle

Triggered 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.end

Triggered 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.message

Triggered when a chat message is sent.

webhooks.cobrowser.start

Triggered when a Cobrowser activity starts in a session.

webhooks.cobrowser.stop

Triggered when a Cobrowser activity stops in a session.

webhooks.transcription.finish

Triggered when a session finishes being transcribed.

{
  "transcriptionUrl": "<pre-signed S3 URL>"
}