# Manage App Users and Sessions

Each app has a `user` model that represents users that can enroll in the application. Whenever a `user` object is created, additional metadata is stored to facilitate enrollment and session management.

A single user may have one or more *sessions*. A session represents a single device that is (or was) signed in.

{% hint style="info" %}
To allow a user to have more than one session, the "Multiple devices per user" feature flag must be enabled for the application.
{% endhint %}

### Parameters

To retrieve, create, update or delete mobile users, follow the instructions in these sections of the documentation for your mobile user object type (e.g. **user**):

* [Retrieve all Objects](https://docs.journeyapps.com/reference/backend-api/api-reference/retrieve-all-objects)
* [Create a New Object](https://docs.journeyapps.com/reference/backend-api/api-reference/create-a-new-object)
* [Update a Single Object](https://docs.journeyapps.com/reference/backend-api/api-reference/update-a-single-object)
* [Delete a Single Object](https://docs.journeyapps.com/reference/backend-api/api-reference/delete-a-single-object)

{% hint style="warning" %}
Deleting the **user** object will lock the user and wipe all app data from the user's enrolled devices. This operation is irreversible.
{% endhint %}

{% hint style="info" %}
**Version compatibility**

* The `sync_status` field with `last_full_sync` is only available for devices with version **4.36.0** or greater of the JourneyApps Container.
* Before managed runtime versions (i.e. before version 4.70), only the installed container version was reported to the backend. Since version 4.70 the runtime version was reported, though it was still erroneously called the "container version" on the backend. As of version 4.82, both the runtime and container versions are reported correctly to the JourneyApps backend.
  {% endhint %}

### User and Sessions API

<table><thead><tr><th width="174">API</th><th width="431.3333333333333">Relative URL</th><th width="145.66666666666674">HTTP Request Method</th></tr></thead><tbody><tr><td><a href="#list-all-users">List all users</a></td><td><code>/api/v4/</code><em><code>backend-deployment-id</code></em><code>/users</code></td><td>GET</td></tr><tr><td><a href="#get-single-user">Get user and sessions</a></td><td><code>/api/v4/</code><em><code>backend-deployment-id</code></em><code>/users/</code><em><code>user-id</code></em></td><td>GET</td></tr><tr><td><a href="#get-single-session">Get single session</a></td><td><code>/api/v4/</code><em><code>backend-deployment-id</code></em><code>/users/</code><em><code>user-id</code></em><code>/sessions/</code><em><code>session-id</code></em></td><td>GET</td></tr><tr><td><a href="#lock-user">Lock user</a></td><td><code>/api/v4/</code><em><code>backend-deployment-id</code></em><code>/users/</code><em><code>user-id</code></em><code>/lock</code></td><td>POST</td></tr><tr><td><a href="#unlock-user">Unlock user</a></td><td><code>/api/v4/</code><em><code>backend-deployment-id</code></em><code>/users/</code><em><code>user-id</code></em><code>/unlock</code></td><td>POST</td></tr><tr><td><a href="#wipe-session">Wipe session</a></td><td><code>/api/v4/</code><em><code>backend-deployment-id</code></em><code>/users/</code><em><code>user-id</code></em><code>/sessions/</code><em><code>session-id</code></em><code>/wipe</code></td><td>POST</td></tr><tr><td><a href="#re-authenticate-session">Re-authenticate session</a></td><td><code>/api/v4/</code><em><code>backend-deployment-id</code></em><code>/users/</code><em><code>user-id</code></em><code>/sessions/</code><em><code>session-id</code></em><code>/re-authenticate</code></td><td>POST</td></tr><tr><td><a href="#generate-authentication-token">Generate authentication token</a></td><td><code>/api/v4/</code><em><code>backend-deployment-id</code></em><code>/users/</code><em><code>user-id</code></em><code>/authentication-token</code></td><td>POST</td></tr></tbody></table>

{% hint style="info" %}
**BASE-URL**

The below examples contain a `BASE-URL` placeholder. Please refer to the [HTTP Endpoints](https://docs.journeyapps.com/reference/introduction#http-endpoints) section to get the base URL relevant to your deployment.
{% endhint %}

#### List all users

API:

```http
GET BASE-URL/api/v4/backend-deployment-id/users[?limit=x&skip=y]
```

Sample request:

```
GET BASE-URL/api/v4/533bda53027894f69b001055/users?limit=2&skip=0
```

Sample response:

{% code title="json" %}

```json
{
  "total": 47,
  "count": 2,
  "more": true,
  "objects": [
  {
    "id": "c8c8c4f8-5013-11e7-a8c7-04017e679e01",
    "last_connected_at": "2017-08-18T13:33:23Z",
    "enrolled": false,
    "locked": false,
    "sessions": [
      {
        "id": "9469407e-8417-11e7-825d-040151508301",
        "state": "LOCKED",
        "last_authenticated_at": "2017-08-18T13:17:26Z",
        "created_at": "2017-08-18T13:17:26Z",
        "signed_out_at": "2017-08-18T13:33:23Z",
        "last_connected_at": "2017-08-18T13:33:23Z",
        "container": {
          "version": "20.6.1",
          "bundle_id": "xyz.appinstall.myapp",
          "platform": "IOS"
        },
        "runtime": {
          "version": "4.82.0"
        },
        "device": {
          "id": "1234-1234-1234-1234"
        },
        "label": "Apple iPhone7,2",
        "sync_status": {
          "last_full_sync": "2018-07-31T12:17:58Z"
        }
      }
    ]
  },
  {
    "id": "5571fb26-54f7-11e7-a8f8-040151508301",
    "last_connected_at": "2017-08-23T10:12:57Z",
    "enrolled": true,
    "locked": false,
    "sessions": [
      {
        "id": "066b26c4-8418-11e7-9ba9-04017e679e01",
        "state": "ENROLLED",
        "last_authenticated_at": "2017-08-18T13:20:37Z",
        "created_at": "2017-08-18T13:20:37Z",
        "signed_out_at": null,
        "last_connected_at": "2017-08-23T10:12:57Z",
        "container": {
          "version": "20.6.1",
          "bundle_id": "xyz.appinstall.myapp",
          "platform": "ANDROID"
        },
        "runtime": {
          "version": "4.82.0"
        },
        "device": {
          "id": "2345-2345-2345-2345"
        },
        "label": "Sony C6903"
      },
      {
        "id": "556ed8a6-54f7-11e7-a8f8-040151508301",
        "state": "LOCKED",
        "last_authenticated_at": null,
        "created_at": null,
        "signed_out_at": "2017-08-18T13:20:30Z",
        "last_connected_at": "2017-06-19T14:19:39Z",
        "container": {
          "version": "20.6.1",
          "bundle_id": "xyz.appinstall.myapp",
          "platform": "CHROME"
        },
        "runtime": {
          "version": "4.82.0"
        },
        "device": {
          "id": "3456-3456-3456-3456"
        },
        "label": "Chrome"
      }
    ]
  }
]
}
```

{% endcode %}

#### Get single user

API:

```
GET /api/v4/backend-deployment-id/users/user-id
```

Sample request:

```
GET BASE-URL/api/v4/533bda53027894f69b001055/users/c8c8c4f8-5013-11e7-a8c7-04017e679e01
```

Sample response:

{% code title="json" %}

```json
{
    "id": "c8c8c4f8-5013-11e7-a8c7-04017e679e01",
    "last_connected_at": "2017-08-18T13:33:23Z",
    "enrolled": false,
    "locked": false,
    "sessions": [
        {
            "id": "9469407e-8417-11e7-825d-040151508301",
            "state": "LOCKED",
            "last_authenticated_at": "2017-08-18T13:17:26Z",
            "created_at": "2017-08-18T13:17:26Z",
            "signed_out_at": "2017-08-18T13:33:23Z",
            "last_connected_at": "2017-08-18T13:33:23Z",
            "container": {
                "version": "20.6.1",
                "bundle_id": "xyz.appinstall.myapp",
                "platform": "IOS"
            },
            "runtime": {
                "version": "4.82.0"
            },
            "device": {
              "id": "3456-3456-3456-3456"
            },
            "label": "Apple iPhone7,2",
            "sync_status": {
                "last_full_sync": "2018-07-31T12:17:58Z"
            }
        }
    ]
}
```

{% endcode %}

#### Get single session

API:

```
GET /api/v4/backend-deployment-id/users/user-id/sessions/session-id
```

Sample request:

```
GET BASE-URL/api/v4/533bda53027894f69b001055/users/c8c8c4f8-5013-11e7-a8c7-04017e679e01/sessions/9469407e-8417-11e7-825d-040151508301
```

Sample response:

{% code title="json" %}

```json
{
    "id": "9469407e-8417-11e7-825d-040151508301",
    "state": "LOCKED",
    "last_authenticated_at": "2017-08-18T13:17:26Z",
    "created_at": "2017-08-18T13:17:26Z",
    "signed_out_at": "2017-08-18T13:33:23Z",
    "last_connected_at": "2017-08-18T13:33:23Z",
    "container": {
        "version": "20.6.1",
        "bundle_id": "xyz.appinstall.myapp",
        "platform": "IOS"
    },
    "runtime": {
        "version": "4.82.0"
    },
    "device": {
      "id": "3456-3456-3456-3456"
    },
    "label": "Apple iPhone7,2",
    "sync_status": {
        "last_full_sync": "2018-07-31T12:17:58Z"
    }
}
```

{% endcode %}

Fields:

<table><thead><tr><th width="260">Field</th><th>Description</th></tr></thead><tbody><tr><td><code>state</code></td><td><code>ENROLLED</code>: Currently enrolled.<br><code>LOCKED</code>: Locked via backend, API, or from the device. Will direct user to the login screen on next connect.<br><code>RESET</code>: Like locked, but will force a data wipe the next time the device connects.<br><code>NEVER_ENROLLED</code>: Only for legacy data.</td></tr><tr><td><code>last_connected_at</code></td><td>Updated every time the device connects via an API call, such as sync or data upload.</td></tr><tr><td><code>created_at</code></td><td>First enrollment date for this session.</td></tr><tr><td><code>last_authenticated_at</code></td><td>Date of the last enrollment call. Should be close to <code>created_at</code> if this is the first enrollment (may not match exactly).</td></tr><tr><td><code>signed_out_at</code></td><td>Date of last sign out (when the state changed to <code>LOCKED</code> or <code>RESET</code>). Stays present when the session enrolls again.</td></tr></tbody></table>

Apart from `last_connected_at`, these values only change when the user enrolls or the session is "locked". Note that in typical cases, the same session is used over multiple enrollments if the same device is used, but a new session is created if the user enrolls using a different device.

#### Lock user

Locking the user will automatically disable the application on all of their devices, as well as prevent them from logging in again.

{% hint style="info" %}
**Note:** A user can be unlocked, in which case they will be able to log in again.
{% endhint %}

If *`wipe`* is true, all application data on the device will be permanently deleted. This can include any data or attachments that have not uploaded to the JourneyApps Backend yet. This action cannot be undone.

API:

```
POST /api/v4/backend-deployment-id/users/user-id/lock

{"wipe": true/false}
```

Or use the [batch operation](https://docs.journeyapps.com/reference/backend-api/api-reference/batch-operations-v4-api):

```json
{
    "method": "users/lock",
    "user_id": "...",
    "wipe": true/false
}
```

{% hint style="warning" %}
**Note:** the *wipe* parameter is required.
{% endhint %}

The response code is 204 if successful.

#### Unlock user

Allow a locked user to log in again.

API:

```
POST /api/v4/backend-deployment-id/users/user-id/unlock
```

Or use the [batch operation](https://docs.journeyapps.com/reference/backend-api/api-reference/batch-operations-v4-api):

```json
{
    "method": "users/unlock",
    "user_id": "..."
}
```

The response code is 204 if successful.

#### Wipe session

This will permanently delete all application data from the specific device. This can include any data or attachments that have not uploaded to the JourneyApps Backend yet. This action cannot be undone.

This does not affect any other sessions, and the user will still be able to log in.

API:

```
POST /api/v4/backend-deployment-id/users/user-id/sessions/session-id/wipe
```

Or use the batch operation:

```json
{
    "method": "users/sessions/wipe",
    "user_id": "...",
    "session_id: "..."
}
```

The response code is 204 if successful.

#### Re-authenticate session

This disables the session, requiring the user to log in again. No data is deleted on the device.

API:

```
POST /api/v4/backend-deployment-id/users/user-id/sessions/session-id/re-authenticate
```

Or use the batch operation:

```json
{
    "method": "users/sessions/re-authenticate",
    "user_id": "...",
    "session_id: "..."
}
```

The response code is 204 if successful.

#### Generate Authentication Token

Generate a temporary token that can be used for enrollment.&#x20;

{% hint style="warning" %}
Authentication tokens expire 5 minutes after being created.
{% endhint %}

If the "multiple devices per user" flag is not enabled for the application, this can only be used to enroll one user at a time.

API:

```
POST /api/v4/backend-deployment-id/users/user-id/authentication-token
```

Or use the batch operation:

```json
{
    "method": "users/authentication-token",
    "user_id": "..."
}
```

Sample Response:

```json
{
    "token": "12345678",
    "url": "https://embark.mobi/enroll?h=internal-testing.journeyapps.com&k=12345678&t=j"
}
```
