# Virtual & Physical Sessions

{% hint style="info" %}
At this time it is important to only advertise virtual classes via your platform - the good news is that virtual data is now available in our platform via the `isVirtual=true` parameter (see [below](https://docs.imin.co/platform-products/search/imin-events-api) for more details). For example, <https://search.imin.co/events-api/v2/event-series?mode=upcoming-sessions&isVirtual=true> will return all virtual classes in our platform.

By using the `isVirtual=true` parameter, any classes that take place in-person at a physical location will not be included in your API results. Once Government restrictions are lifted, this parameter can be used to return both virtual (`isVirtual=true`) and in-person (`isVirtual=false`) classes.
{% endhint %}

## 1. Attendance Mode

Attendance Mode differentiates between sessions that occur physically, virtually or both. Please see the OpenActive discussion for this field [here](https://github.com/openactive/modelling-opportunity-data/issues/225).

### 1.1. Offline Attendance (AKA Physical)

* Response field (in EventSeries): `"eventAttendanceMode": "schema:OfflineEventAttendanceMode"`

Sessions that only occur at a physical location. For example, they may occur at a leisure centre, park or gym.

{% hint style="info" %}
Offline Attendance sessions **must** have location data, which is stored in the SessionSeries' `location` field.
{% endhint %}

Additionally, when searching for Offline Attendance sessions, location search parameter `geo[radial]` is **required**.

### 1.2. Online Attendance (AKA Virtual)

* Response field (in EventSeries): `"eventAttendanceMode": "schema:OnlineEventAttendanceMode"`

Fully virtual sessions that do not occur at a physical location, but occur virtually. For example, a yoga class with an instructor using a video conference where attendees can view the instructor and the instructor can view the attendees.

{% hint style="success" %}
Online Attendance sessions **may** have location data, which is stored in the SessionSeries' `location` field.
{% endhint %}

For fully online sessions, location data simply refers to the location that the organisation is affiliated with.  **Do not** advertise that potential attendees visit this location. It is important to make this clear. The reason for including location data for fully virtual sessions is to satisfy use cases where organisations wish to support local activity providers, e.g. a local authority wanting to promote virtual sessions from the local fitness businesses in their constituency over and above other virtual sessions from elsewhere.

Online Attendance sessions **may** also have **virtual** location data. This is stored in the ScheduledSession's `beta:virtualLocation` field. Virtual location data is distinct from (physical) location data as it refers not to a physical place but a virtual place like a URL. In OpenActive, this is defined [here](https://github.com/openactive/modelling-opportunity-data/issues/224).

When searching for Online Attendance sessions and not Offline or Mixed Attendance sessions, location search parameter `geo[radial]` is **optional**.

### 1.3. Mixed Attendance

* Response field (in EventSeries): `"eventAttendanceMode": "schema:MixedEventAttendanceMode"`

These are sessions that can be attended at a physical *or* virtual location.

{% hint style="info" %}
Mixed Attendance sessions **must** have location data and **may** have virtual location data. These are stored in the SessionSeries' `location` and ScheduledSession's `beta:virtualLocation` field respectively.
{% endhint %}

When searching for Mixed Attendance sessions, location search parameter `geo[radial]` is **required**.

{% hint style="warning" %}
It is important to consider how the different modes will be communicated to the end user on the front end.

For example, during the Government restrictions, `schema:OnlineEventAttendanceMode` might render something like "*Online Video*". When the restrictions start to be lifted, think about how sessions with`schema:MixedEventAttendanceMode` (e.g. "*Online video and in-person*") and`schema:OfflineEventAttendanceMode` (e.g. "*In-person*") will be presented to the end user.
{% endhint %}

## 2. Search Modes

Supported [Search modes](https://docs.imin.co/platform-products/search/imin-events-api/filters/modes) for Searches that may include Virtual Sessions:

* `upcoming-sessions`: sessions are sorted by the date and time that they occur. Earlier sessions are shown first and later sessions are shown last.

## 3. `imin:locationSummary`

Please note that we will be removing `imin:locationSummary` from search results **where it is empty**, i.e. where it includes information about a virtual session, like the following example:

```javascript
"imin:locationSummary": [
{
"id": "#/imin:locationSummary/bfabc72914160a1478979f235bd484f9e357c023",
"type": "Place",
"name": "LIVESTREAM",
"address": {
"type": "PostalAddress",
"imin:fullAddress": "LIVESTREAM"
},
"geo": {
"type": "GeoCoordinates",
"latitude": 0,
"longitude": 0
}
}
]
```

With this in mind, it is worth considering the following:

1. Look at `imin:locationSummary` in the API results.
2. If it has at least one item:
   * This will pertain to a physical location, so print `locationSummary[0].name`.
   * This will display the physical location so people can go to the in-person part of the session if they wish/are allowed to do so.
3. If it has no items:
   * Print “*N/A*” or “*Online Video*” or similar to illustrate that it does not have a physical location.

{% hint style="danger" %}
At the moment you might be using "*LIVESTREAM*", which is included at `locationSummary.name`(see example above). However, in future, `imin:locationSummary` will not exist where there is no information related to a physical location. Therefore, we recommend that you do not code against `imin:locationSummary` where it has no information.
{% endhint %}

## 4. Optional Query Parameters - Virtual Sessions

The following query parameters are related to searches made for **virtual sessions**.

{% hint style="info" %}
Query params are prefixed with `virtual-` if they are only meaningful for virtual sessions.
{% endhint %}

### `isVirtual`

Possible values for the `isVirtual` parameter are as follows:

* `true`: only sessions which occur virtually will be returned. This includes sessions with event attendance mode:
  * `schema:OnlineEventAttendanceMode`; and
  * `schema:MixedEventAttendanceMode`.<br>
* `false`: only sessions which occur physically will be returned. This includes sessions with event attendance mode:
  * `schema:OfflineEventAttendanceMode`; and
  * `schema:MixedEventAttendanceMode`.<br>
* Not specified: where `isVirtual` is not included in an API call, all three event attendance modes can be returned:
  * `schema:OnlineEventAttendanceMode`;
  * `schema:MixedEventAttendanceMode`; and
  * `schema:OfflineEventAttendanceMode`.

{% hint style="warning" %}
The behaviour of the `isVirtual` parameter is dictated by use of the `geo[radial]` parameter, as set out below.
{% endhint %}

### `geo[radial]`

This field is required for non-virtual searches and optional for virtual searches (i.e. where `isVirtual=true`).

{% hint style="danger" %}
To return **all available** virtual classes, you must:

* **include**`isVirtual=true`; and
* **exclude** `geo[radial]`.
  {% endhint %}

Virtual sessions have a `beta:affiliatedLocation` rather than a `location` field ([OpenActive discussion](https://github.com/openactive/modelling-opportunity-data/issues/227#issuecomment-604309046)). For Virtual sessions, `geo[radial]` filters on `beta:affiliatedLocation`.\
Use this to, for example, find virtual sessions that are affiliated with your local borough.

{% hint style="info" %}
**Note:** if the `geo[radial]` parameter is included, only those virtual-only sessions that have either a `location` or a `beta:affiliatedLocation` will be included in the results.

This is because using`geo[radial]` with `isVirtual=true` has been designed for those users who specifically want to find virtual classes from “local” providers. API calls using these parameters will only return a subset of the available virtual classes.
{% endhint %}

{% hint style="success" %}

* [https://search.imin.co/events-api/v2/event-series?mode=upcoming-sessions&**isVirtual=true**](https://search.imin.co/events-api/v2/event-series?mode=upcoming-sessions\&isVirtual=true) will deliver **all virtual classes** available via the API.<br>
* [https://search.imin.co/events-api/v2/event-series?mode=upcoming-sessions&**geo\[radial\]=51.2422774,-0.7294026,1000\&isVirtual=true**](https://search.imin.co/events-api/v2/event-series?mode=upcoming-sessions\&geo\[radial]=51.2422774,-0.7294026,1000\&isVirtual=true) will deliver **a smaller subset of virtual classes**, i.e. only those with an actual location included.
  {% endhint %}

### `isVirtuallyCoached`

Is the coaching pre-recorded or live? This query parameter can also be used for non-virtual sessions (e.g. a spinning class that takes place in a gym with a pre-recorded coach). This is why it is not prefixed with `virtual-`. Possible values for this parameter include:

* `true`: coach is pre-recorded; and<br>
* `false`: coach is live.

### `levelType`

For attending virtual sessions, it is especially important to match your own level. This is particularly important for beginners who either want to try something new or have just started. For this, use `levelType=imin:BeginnerLevel`.

### `virtualIsInteractivityPreferred`

Possible values for this parameter include:

* `true`: sessions where the attendee and instructor are advised to interact, e.g. a video conference where all participants can be seen and heard; and<br>
* `false`: sessions where the attendee and instructor cannot interact, e.g. a live stream where only the instructor can be seen and heard.

{% hint style="info" %}
Combine `isVirtuallyCoached=false&virtualIsInteractivityPreferred=true` to find virtual sessions that are fully interactive between instructor and attendee. In these sessions, attendees can potentially receive live feedback.
{% endhint %}

### `virtualUsesParticipantSuppliedEquipment` ([OpenActive discussion](https://github.com/openactive/modelling-opportunity-data/issues/229#issuecomment-604331887))

Possible values for this query parameter include:

* `true`: the attendee must have some home equipment in order to participate properly, e.g. a yoga mat. This includes sessions with `beta:participantSuppliedEquipment` values:

  * `https://openactive.io/Required`(`oa:Required`); and
  * `https://openactive.io/Optional`(`oa:Optional`).

* `false`: the attendee does not need any home equipment in order to participate, e.g. calisthenics. This includes sessions with `beta:participantSuppliedEquipment` values:
  * `https://openactive.io/Optional`; and
  * `https://openactive.io/Unavailable`(`oa:Unavailable`).

{% hint style="info" %}
All of the above query parameters are all optional. Excluding the field means that sessions with any possible value are returned.
{% endhint %}

## **5. Response data**

A Virtual Session will have the following fields:

### **EventSeries**

* `eventAttendanceMode`: (STRING) either:
  * `schema:OnlineEventAttendanceMode`; or
  * `schema:MixedEventAttendanceMode`.<br>
* `beta:isInteractivityPreferred`: (BOOLEAN) is this a session where attendee and instructor can interact?<br>
* `beta:participantSuppliedEquipment`: (STRING) does the attendee need to have home equipment in order to participate properly? One of:
  * `oa:Required` - equipment is required;
  * `oa:Optional` - equipment is optional, and the participant can improvise; or
  * `oa:Unavailable` - no equipment required.

### **SessionSeries**

* `location`: this field will **NOT** be included for virtual-only sessions, i.e. where`eventAttendanceMode`is `schema:OnlineEventAttendanceMode`.

{% hint style="info" %}
To ease the transition to including virtual sessions, virtual sessions are going to include a dummy location so that Events API clients do not break. This looks like:

```javascript
{
  "type": "Place",
  "name": "LIVESTREAM",
  "address": {
    "type": "PostalAddress",
    "imin:fullAddress": "LIVESTREAM"
  },
  "geo": {
    "type": "GeoCoordinates",
    "latitude": 0,
    "longitude": 0
  }
}
```

This is just a temporary measure. Eventually, virtual sessions will have no location whatsoever, so please account for sessions with no location data.
{% endhint %}

* `beta:affiliatedLocation`: ([Place](https://www.openactive.io/modelling-opportunity-data/#describing-locations-code-schema-place-code-)) where the virtual session was physically located before it moved online.

### **ScheduledSession**

* `beta:virtualLocation`: (VirtualLocation) where the session is virtually located (e.g. a URL).
* `maximumVirtualAttendeeCapacity`: (NUMBER) the maximum number of connections to a shared virtual space.

An example, which only includes the salient data, of a search response that contains virtual sessions:

```javascript
{
 "@context": ["https://openactive.io/", "https://schema.imin.co/"],
 "type": "imin:RestrictedCollection",
 "id": "https://search.imin.co/events-api/v2/event-series?mode=upcoming-sessions&isVirtual=true",
 "imin:totalItems": 3572,
 "view": {
  "type": "PartialCollectionView",
  "id": "https://search-test.imin.co/events-api/v2/event-series?mode=upcoming-sessions&isVirtual=true&page=1",
  // ..etc
 },
 "imin:item": [
  {
   "type": "EventSeries",
   "name": "Yoga with Franz K",
   "eventAttendanceMode": "schema:OnlineEventAttendanceMode",
   "beta:isInteractivityPreferred": true,
   "beta:participantSuppliedEquipment": "oa:Optional",
   "subEvent": [
    {
     "type": "SessionSeries",
     "beta:affiliatedLocation": {
       "type": "Place",
       "name": "Castle Leisure Centre",
       // ..etc - More Place data
     },
     "subEvent": [
      {
       "type": "ScheduledSession",
       "startDate": "2020-03-23T11:45:00Z",
       "endDate": "2020-03-23T12:45:00Z",
       "beta:virtualLocation": {
        "@type": "VirtualLocation",
        "name": "Zoom Video Chat",
        "url": "https://zoom.us/j/1234567890/signup"
       },
       "maximumVirtualAttendeeCapacity": 30
      },
     ],
     // ..etc - More SessionSeries data
    },
   ],
   // ..etc - More EventSeries data
  },
 // ..etc - More results
 ]
}
```

## **6. The API and front end UX**

We have been working with activity providers on the information about virtual classes that should be included as standard in the open data. It is recommended that they include the following information at a minimum:

* Class description;
* The URL for livestream classes (if available);
* Organiser name;
* Organiser website and social media;
* Price; and
* Whether any equipment is required and if so, what equipment\*.

Therefore, we recommend that your front end platform caters for the presence of this information in the API results.

**\*** NB where `beta:participantSuppliedEquipment` is `oa:Required`, providers are being encouraged to provide clarification on what equipment is required in either `attendeeInstruction` or `description` (see [here](https://developer.openactive.io/publishing-data/virtual-events#values-2) for further details).

{% hint style="info" %}
**Call-to-action URLs**

Once an end user has found a session they want to attend, they will be presented with a call-to-action button. In the perfect world, this would be a "book now" button, however, in the absence of `beta:virtualLocation.url`, we advise building against the following (in order of preference):

1. `subEvent[].subEvent[].url` (found in the ScheduledSession `subEvent` object), where it exists;
2. `subEvent[].url` (in the SessionsSeries `subEvent` object), where it exists; or
3. `organiser.url`, where it exists.
   {% endhint %}
